예제 #1
0
    def superdense_coding_program(self, bit0: int, bit1: int):
        raw_prog = Program()
        ro = raw_prog.declare('ro', 'BIT', 2)
        # Prepare Bell pair
        raw_prog += gates.H(0)
        raw_prog += gates.CNOT(0, 1)
        # Alice controls qubit 0 and Bob controls 1
        if bit0 == 0 and bit1 == 0:
            pass
        if bit0 == 0 and bit1 == 1:
            raw_prog += gates.X(0)
        if bit0 == 1 and bit1 == 0:
            raw_prog += gates.Z(0)
        if bit0 == 1 and bit1 == 1:
            raw_prog += gates.X(0)
            raw_prog += gates.Z(0)
        # Now Alice sends qubit 0 to Bob
        # Bob rotates from Bell basis to standard basis
        raw_prog += gates.CNOT(0, 1)
        raw_prog += gates.H(0)
        # Measure qubits into Bob's registers
        raw_prog += gates.MEASURE(0, ro[0])
        raw_prog += gates.MEASURE(1, ro[1])

        new_prog = ftqc.rewrite_program(raw_prog, self.steane_7bit)

        results = self.run_program(new_prog)
        for result in results:
            self.assertEqual(result[0], bit0)
            self.assertEqual(result[1], bit1)
예제 #2
0
def tiny_ansatz_1(current_params):
    "Previously used for Hydrogen VQE in Rigetti implementation"

    return pyquil.quil.Program(g.X(0), g.X(1), g.RX(-np.pi / 2, 0),
                               g.RY(np.pi / 2, 1), g.CNOT(0, 1),
                               g.RZ(current_params[0], 1), g.CNOT(0, 1),
                               g.RX(np.pi / 2, 0), g.RY(-np.pi / 2, 1))
예제 #3
0
    def test_convert_program_with_controlled_operations(self):
        """Test that a program with controlled operations is properly converted."""
        program = pyquil.Program()

        program += g.RZ(0.34, 1)
        program += g.RY(0.2, 3).controlled(2)
        program += g.RX(0.4, 2).controlled(0)
        program += g.CNOT(1, 4)
        program += g.CNOT(1, 6).controlled(3)
        program += g.X(3).controlled(4).controlled(1)

        with OperationRecorder() as rec:
            load_program(program)(wires=range(6))

        expected_queue = [
            qml.RZ(0.34, wires=[1]),
            qml.CRY(0.2, wires=[2, 3]),
            qml.CRX(0.4, wires=[0, 2]),
            qml.CNOT(wires=[1, 4]),
            plf.ops.CCNOT(wires=[3, 1, 5]),
            plf.ops.CCNOT(wires=[1, 4, 3]),
        ]

        for converted, expected in zip(rec.queue, expected_queue):
            assert converted.name == expected.name
            assert converted.wires == expected.wires
            assert converted.params == expected.params
예제 #4
0
    def test_convert_program_with_defpermutationgates(self):
        """Test that a program with gates defined via DefPermutationGate is 
        properly converted."""
        program = pyquil.Program()

        expected_matrix = np.eye(4)
        expected_matrix = expected_matrix[:, [1, 0, 3, 2]]

        x_plus_x_definition = pyquil.quil.DefPermutationGate(
            "X+X", [1, 0, 3, 2])
        X_plus_X = x_plus_x_definition.get_constructor()

        program += x_plus_x_definition

        program += g.CNOT(0, 1)
        program += X_plus_X(0, 1)
        program += g.CNOT(0, 1)

        with OperationRecorder() as rec:
            load_program(program)(wires=range(2))

        expected_queue = [
            qml.CNOT(wires=[0, 1]),
            qml.QubitUnitary(expected_matrix, wires=[0, 1]),
            qml.CNOT(wires=[0, 1]),
        ]

        for converted, expected in zip(rec.queue, expected_queue):
            assert converted.name == expected.name
            assert converted.wires == expected.wires
            assert np.array_equal(converted.params, expected.params)
예제 #5
0
    def noisy_encode_plus(self, qubits: List[Union[QubitPlaceholder, int]]) -> Program:
        """
        Construct a program preparing a new logical qubit in the |+> state (+1 eigenstate of \hat X).
        The qubits must all be reset to the physical |0> state at the beginning of this program. The
        preparation is not fault tolerant and any physical errors that occur during preparation may
        create many correlated errors in the code block.
        """
        # See implementation of noisy_encode_zero for more detailed comments.
        n, r_1, r_2 = self.n, self.r_1, self.r_2

        # The idea is that we want to transform the parity check matrix from
        #
        # [[ 0 0 0 | I1  0  0 ],     [[ I1 A1 A2 | 0  0  0 ],
        #  [ 0 0 0 | 0  I2  0 ],  =>  [  0  0  0 | D I2  E ],
        #  [ 0 0 0 | 0   0 I3 ]]      [  0 ET I3 | 0  0  0 ]]

        # The program accumulates the actual operations on the qubits.
        prog = Program()

        # Step 1: Apply Hadamards to move I1 and I3 to the X side. Post-state:
        #
        # [[ I1 0  0 | 0  0 0 ],
        #  [  0 0  0 | 0 I2 0 ],
        #  [  0 0 I3 | 0  0 0 ]]
        for i in range(r_1):
            prog += gates.H(qubits[i])
        for i in range(r_1 + r_2, n):
            prog += gates.H(qubits[i])

        # Step 2: Copy Z's from I2 to E. This has the side effect of constructing ET. Post-state:
        #
        # [[ I1  0  0 | 0  0 0 ],
        #  [  0  0  0 | 0 I2 E ],
        #  [  0 ET I3 | 0  0 0 ]]
        for i in range(r_1, r_1 + r_2):
            for j in range(r_1 + r_2, n):
                if self.parity_check_c2[i - r_1, j] == 1:
                    prog += gates.CNOT(qubits[j], qubits[i])

        # Step 3: Copy X's from I1 to A1 and A2. This has the side effect of constructing D.
        # Post-state:
        #
        # [[ I1 A1 A2 | 0  0 0 ],
        #  [  0  0  0 | D I2 E ],
        #  [  0 ET I3 | 0  0 0 ]]
        for i in range(r_1):
            for j in range(r_1, n):
                if self.parity_check_c1[i, j] == 1:
                    prog += gates.CNOT(qubits[i], qubits[j])

        return prog
예제 #6
0
    def test_forked_gate_error(self):
        """Test that an error is raised if conversion of a 
        forked gate is attempted."""
        program = pyquil.Program()

        program += g.CNOT(0, 1)
        program += g.RX(0.3, 1).forked(2, [0.5])
        program += g.CNOT(0, 1)

        with pytest.raises(
                qml.DeviceError,
                match=
                "Forked gates can not be imported into PennyLane, as this functionality is not supported",
        ):
            load_program(program)(wires=range(3))
예제 #7
0
    def test_convert_program_with_controlled_operations_not_in_pl_core(
            self, tol):
        """Test that a program with controlled operations out of scope of PL core/PLF
        is properly converted, i.e. the operations are replaced with controlled operations."""
        program = pyquil.Program()

        CS_matrix = np.eye(4, dtype=complex)
        CS_matrix[3, 3] = 1j

        CCT_matrix = np.eye(8, dtype=complex)
        CCT_matrix[7, 7] = np.exp(1j * np.pi / 4)

        program += g.CNOT(0, 1)
        program += g.S(0).controlled(1)
        program += g.S(1).controlled(0)
        program += g.T(0).controlled(1).controlled(2)
        program += g.T(1).controlled(0).controlled(2)
        program += g.T(2).controlled(1).controlled(0)

        with OperationRecorder() as rec:
            load_program(program)(wires=range(3))

        expected_queue = [
            qml.CNOT(wires=[0, 1]),
            qml.QubitUnitary(CS_matrix, wires=[1, 0]),
            qml.QubitUnitary(CS_matrix, wires=[0, 1]),
            qml.QubitUnitary(CCT_matrix, wires=[2, 1, 0]),
            qml.QubitUnitary(CCT_matrix, wires=[2, 0, 1]),
            qml.QubitUnitary(CCT_matrix, wires=[0, 1, 2]),
        ]

        for converted, expected in zip(rec.queue, expected_queue):
            assert converted.name == expected.name
            assert converted.wires == expected.wires
            assert np.allclose(converted.data, expected.data, atol=tol, rtol=0)
예제 #8
0
    def test_load_program_via_entry_point(self):
        """Test that a pyquil Program instance can be loaded via the load entrypoint."""
        program = pyquil.Program()

        program += g.H(0)
        program += g.RZ(0.34, 1)
        program += g.CNOT(0, 3)
        program += g.H(2)
        program += g.H(7)
        program += g.X(7)
        program += g.Y(1)
        program += g.RZ(0.34, 1)

        with OperationRecorder() as rec:
            qml.load(program, format="pyquil_program")(wires=range(5))

        # The wires should be assigned as
        # 0  1  2  3  7
        # 0  1  2  3  4

        expected_queue = [
            qml.Hadamard(0),
            qml.RZ(0.34, wires=[1]),
            qml.CNOT(wires=[0, 3]),
            qml.Hadamard(2),
            qml.Hadamard(4),
            qml.PauliX(4),
            qml.PauliY(1),
            qml.RZ(0.34, wires=[1]),
        ]

        for converted, expected in zip(rec.queue, expected_queue):
            assert converted.name == expected.name
            assert converted.wires == expected.wires
            assert converted.params == expected.params
예제 #9
0
    def test_convert_simple_program_wire_assignment(self):
        """Test that the assignment of qubits to wires works as expected."""
        program = pyquil.Program()

        program += g.H(0)
        program += g.RZ(0.34, 1)
        program += g.CNOT(0, 3)
        program += g.H(2)
        program += g.H(7)
        program += g.X(7)
        program += g.Y(1)
        program += g.RZ(0.34, 1)

        with OperationRecorder() as rec:
            load_program(program)(wires=[3, 6, 4, 9, 1])

        # The wires should be assigned as
        # 0  1  2  3  7
        # 3  6  4  9  1

        expected_queue = [
            qml.Hadamard(3),
            qml.RZ(0.34, wires=[6]),
            qml.CNOT(wires=[3, 9]),
            qml.Hadamard(4),
            qml.Hadamard(1),
            qml.PauliX(1),
            qml.PauliY(6),
            qml.RZ(0.34, wires=[6]),
        ]

        for converted, expected in zip(rec.queue, expected_queue):
            assert converted.name == expected.name
            assert converted.wires == expected.wires
            assert converted.params == expected.params
예제 #10
0
    def test_default_gates(self):
        prog = Program()
        qreg = prog.qalloc(3)

        for op in pygates_1qb:
            prog.apply(op, qreg[0])

        for op in pygates_2qb:
            prog.apply(op, qreg[0], qreg[1])

        prog.apply(CCNOT, qreg[0], qreg[1], qreg[2])

        expected = prog.to_circ()
        #result = qlm_to_pyquil(qlm_circuit)
        # print(result)
        result = Prg()
        for op in quil_1qb:
            result += op(0)
        for op in quil_params:
            result += op(3.14, 0)

        result += pg.SWAP(0, 1)
        result += pg.CNOT(0, 1)
        for op in quil_ctrl:
            result += op(1).controlled(0)
        for op in quil_ctrl_prm:
            result += op(3.14, 1).controlled(0)

        result += pg.CCNOT(0, 1, 2)

        qlm_circuit = pyquil_to_qlm(result)
        exp_str = print_aq(expected)
        res_str = print_aq(qlm_circuit)
        self.assertEqual(exp_str, res_str)
예제 #11
0
    def test_convert_program_with_inverses(self):
        """Test that a program with inverses is properly converted."""
        program = pyquil.Program()

        program += g.H(0)
        program += g.RZ(0.34, 1).dagger()
        program += g.CNOT(0, 3).dagger()
        program += g.H(2)
        program += g.H(7).dagger().dagger()
        program += g.X(7).dagger()
        program += g.X(7)
        program += g.Y(1)
        program += g.RZ(0.34, 1)

        with OperationRecorder() as rec:
            load_program(program)(wires=range(5))

        expected_queue = [
            qml.Hadamard(0),
            qml.RZ(0.34, wires=[1]).inv(),
            qml.CNOT(wires=[0, 3]).inv(),
            qml.Hadamard(2),
            qml.Hadamard(4),
            qml.PauliX(4).inv(),
            qml.PauliX(4),
            qml.PauliY(1),
            qml.RZ(0.34, wires=[1]),
        ]

        for converted, expected in zip(rec.queue, expected_queue):
            assert converted.name == expected.name
            assert converted.wires == expected.wires
            assert converted.params == expected.params
예제 #12
0
    def test_program_in_qnode(self, angle):
        """Test how a simple program is used inside a QNode."""
        program = pyquil.Program()

        delta = program.declare("delta", "REAL")

        program += g.RX(delta, 0)
        program += g.CNOT(0, 1)

        loader = qml.load(program, format="pyquil_program")
        dev = qml.device("default.qubit", wires=2)

        @qml.qnode(dev)
        def circuit(a):
            loader(wires=[0, 1], parameter_map={delta: a})

            return qml.expval(qml.PauliZ(0)), qml.expval(qml.PauliZ(1))

        @qml.qnode(dev)
        def circuit_reg(a):
            qml.RX(a, wires=[0])
            qml.CNOT(wires=[0, 1])

            return qml.expval(qml.PauliZ(0)), qml.expval(qml.PauliZ(1))

        assert np.array_equal(circuit(angle), circuit_reg(angle))
예제 #13
0
    def test_convert_simple_program(self):
        """Test that a simple program is properly converted."""
        program = pyquil.Program()

        program += g.H(0)
        program += g.RZ(0.34, 1)
        program += g.CNOT(0, 3)
        program += g.H(2)
        program += g.H(7)
        program += g.X(7)
        program += g.Y(1)
        program += g.RZ(0.34, 1)

        with OperationRecorder() as rec:
            load_program(program)(wires=range(5))

        # The wires should be assigned as
        # 0  1  2  3  7
        # 0  1  2  3  4

        expected_queue = [
            qml.Hadamard(0),
            qml.RZ(0.34, wires=[1]),
            qml.CNOT(wires=[0, 3]),
            qml.Hadamard(2),
            qml.Hadamard(4),
            qml.PauliX(4),
            qml.PauliY(1),
            qml.RZ(0.34, wires=[1]),
        ]

        for converted, expected in zip(rec.queue, expected_queue):
            assert converted.name == expected.name
            assert converted.wires == expected.wires
            assert converted.params == expected.params
예제 #14
0
    def test_convert_simple_program_with_parameters_mixed_keys(self):
        """Test that a parametrized program is properly converted when
        the variable map contains mixed key types."""
        program = pyquil.Program()

        alpha = program.declare("alpha", "REAL")
        beta = program.declare("beta", "REAL")
        gamma = program.declare("gamma", "REAL")
        delta = program.declare("delta", "REAL")

        program += g.H(0)
        program += g.CNOT(0, 1)
        program += g.RX(alpha, 1)
        program += g.RZ(beta, 1)
        program += g.RX(gamma, 1)
        program += g.CNOT(0, 1)
        program += g.RZ(delta, 0)
        program += g.H(0)

        a, b, c, d = 0.1, 0.2, 0.3, 0.4

        parameter_map = {
            "alpha": a,
            beta: b,
            gamma: c,
            "delta": d,
        }

        with OperationRecorder() as rec:
            load_program(program)(wires=range(2), parameter_map=parameter_map)

        expected_queue = [
            qml.Hadamard(0),
            qml.CNOT(wires=[0, 1]),
            qml.RX(0.1, wires=[1]),
            qml.RZ(0.2, wires=[1]),
            qml.RX(0.3, wires=[1]),
            qml.CNOT(wires=[0, 1]),
            qml.RZ(0.4, wires=[0]),
            qml.Hadamard(0),
        ]

        for converted, expected in zip(rec.queue, expected_queue):
            assert converted.name == expected.name
            assert converted.wires == expected.wires
            assert converted.params == expected.params
예제 #15
0
    def noisy_encode_zero(self, qubits: List[Union[QubitPlaceholder, int]]) -> Program:
        """
        Construct a program preparing a new logical qubit in the |0> state (+1 eigenstate of \hat Z).
        The qubits must all be reset to the physical |0> state at the beginning of this program. The
        preparation is not fault tolerant and any physical errors that occur during preparation may
        create many correlated errors in the code block.
        """
        n, r_1, r_2 = self.n, self.r_1, self.r_2

        # We are starting with all qubits in the |0> state, meaning they are stabilised by
        # Z_1, Z_2, ..., Z_n. We want to do a unitary transformation to a state stabilised by the
        # code stabilisers along with the stabilisers for the logical 0 state. In general, if a
        # state |ᴪ> is stabilised by S, then U|ᴪ> is stabilised by USU†. We can perform Clifford
        # gate operations to transform the stabiliser set. For details see Nielsen & Chuang
        # section 10.5.2 and Problem 10.3. Also, see Appendix A of "Fault-tolerant Preparation of
        # Stabilizer States for Quantum CSS Codes by ClassicalError-Correcting Codes."
        #
        # The idea is that we want to transform the parity check matrix from
        #
        # [[ 0 0 0 | I1  0  0 ],     [[ I1 A1 A2 | 0    0  0 ],
        #  [ 0 0 0 | 0  I2  0 ],  =>  [  0  0  0 | D   I2  E ],
        #  [ 0 0 0 | 0   0 I3 ]]      [  0  0  0 | A2T  0 I3 ]]
        #
        # Transformations to manipulate the parity check are derived from Figure 10.7 in
        # Nielsen & Chuang which shows how Pauli operators behave under conjugation by Clifford
        # operators.

        # The program accumulates the actual operations on the qubits.
        prog = Program()

        # Step 0: Copy Z's from I3 to E. Post-state:
        #
        # [[ I1 0 0 | 0  0  0 ],
        #  [  0 0 0 | 0 I2  E ],
        #  [  0 0 0 | 0  0 I3 ]]
        #
        # This is just a multiplication of stabilisers and does not require any instructions.

        # Step 1: Apply Hadamards to move I1 to the X side. Post-state:
        #
        # [[ I1 0 0 | 0  0  0 ],
        #  [  0 0 0 | 0 I2  E ],
        #  [  0 0 0 | 0  0 I3 ]]
        for i in range(r_1):
            prog += gates.H(qubits[i])

        # Step 2: Copy X's from I1 to A1 and A2. This has the side effect of constructing D and A2T.
        # Post-state:
        #
        # [[ I1 A1 A2 |   0  0  0 ],
        #  [  0  0  0 |   D I2  E ],
        #  [  0  0  0 | A2T  0 I3 ]]
        for i in range(r_1):
            for j in range(r_1, n):
                if self.parity_check_c1[i, j] == 1:
                    prog += gates.CNOT(qubits[i], qubits[j])

        return prog
예제 #16
0
    def test_convert_program_with_defgates(self):
        """Test that a program that defines its own gates is properly converted."""
        program = pyquil.Program()

        sqrt_x = np.array([[0.5 + 0.5j, 0.5 - 0.5j], [0.5 - 0.5j, 0.5 + 0.5j]])

        sqrt_x_t2 = np.kron(sqrt_x, sqrt_x)
        sqrt_x_t3 = np.kron(sqrt_x, sqrt_x_t2)

        sqrt_x_definition = pyquil.quil.DefGate("SQRT-X", sqrt_x)
        SQRT_X = sqrt_x_definition.get_constructor()
        sqrt_x_t2_definition = pyquil.quil.DefGate("SQRT-X-T2", sqrt_x_t2)
        SQRT_X_T2 = sqrt_x_t2_definition.get_constructor()
        sqrt_x_t3_definition = pyquil.quil.DefGate("SQRT-X-T3", sqrt_x_t3)
        SQRT_X_T3 = sqrt_x_t3_definition.get_constructor()

        program += sqrt_x_definition
        program += sqrt_x_t2_definition
        program += sqrt_x_t3_definition

        program += g.CNOT(0, 1)
        program += SQRT_X(0)
        program += SQRT_X_T2(1, 2)
        program += SQRT_X_T3(1, 0, 2)
        program += g.CNOT(0, 1)
        program += g.CNOT(1, 2)
        program += g.CNOT(2, 0)

        with OperationRecorder() as rec:
            load_program(program)(wires=range(3))

        expected_queue = [
            qml.CNOT(wires=[0, 1]),
            qml.QubitUnitary(sqrt_x, wires=[0]),
            qml.QubitUnitary(sqrt_x_t2, wires=[1, 2]),
            qml.QubitUnitary(sqrt_x_t3, wires=[1, 0, 2]),
            qml.CNOT(wires=[0, 1]),
            qml.CNOT(wires=[1, 2]),
            qml.CNOT(wires=[2, 0]),
        ]

        for converted, expected in zip(rec.queue, expected_queue):
            assert converted.name == expected.name
            assert converted.wires == expected.wires
            assert converted.params == expected.params
예제 #17
0
    def test_convert_simple_program_with_parameters(self):
        """Test that a simple program with parameters is properly converted."""
        program = pyquil.Program()

        alpha = program.declare("alpha", "REAL")
        beta = program.declare("beta", "REAL")
        gamma = program.declare("gamma", "REAL")

        program += g.H(0)
        program += g.CNOT(0, 1)
        program += g.RX(alpha, 1)
        program += g.RZ(beta, 1)
        program += g.RX(gamma, 1)
        program += g.CNOT(0, 1)
        program += g.H(0)

        a, b, c = 0.1, 0.2, 0.3

        parameter_map = {
            "alpha": a,
            "beta": b,
            "gamma": c,
        }

        with OperationRecorder() as rec:
            load_program(program)(wires=range(2), parameter_map=parameter_map)

        expected_queue = [
            qml.Hadamard(0),
            qml.CNOT(wires=[0, 1]),
            qml.RX(0.1, wires=[1]),
            qml.RZ(0.2, wires=[1]),
            qml.RX(0.3, wires=[1]),
            qml.CNOT(wires=[0, 1]),
            qml.Hadamard(0),
        ]

        for converted, expected in zip(rec.queue, expected_queue):
            assert converted.name == expected.name
            assert converted.wires == expected.wires
            assert converted.params == expected.params
예제 #18
0
    def test_convert_program_with_controlled_dagger_operations(self):
        """Test that a program that combines controlled and daggered operations
        is properly converted."""
        program = pyquil.Program()

        program += g.CNOT(0, 1).controlled(2)
        program += g.CNOT(0, 1).dagger().controlled(2)
        program += g.CNOT(0, 1).controlled(2).dagger()
        program += g.CNOT(0, 1).dagger().controlled(2).dagger()
        program += g.RX(0.3, 3).controlled(4)
        program += g.RX(0.2, 3).controlled(4).dagger()
        program += g.RX(0.3, 3).dagger().controlled(4)
        program += g.RX(0.2, 3).dagger().controlled(4).dagger()
        program += g.X(2).dagger().controlled(4).controlled(1).dagger()
        program += g.X(0).dagger().controlled(4).controlled(1)
        program += g.X(0).dagger().controlled(4).dagger().dagger().controlled(
            1).dagger()

        with OperationRecorder() as rec:
            load_program(program)(wires=range(5))

        expected_queue = [
            plf.ops.CCNOT(wires=[2, 0, 1]),
            plf.ops.CCNOT(wires=[2, 0, 1]).inv(),
            plf.ops.CCNOT(wires=[2, 0, 1]).inv(),
            plf.ops.CCNOT(wires=[2, 0, 1]),
            qml.CRX(0.3, wires=[4, 3]),
            qml.CRX(0.2, wires=[4, 3]).inv(),
            qml.CRX(0.3, wires=[4, 3]).inv(),
            qml.CRX(0.2, wires=[4, 3]),
            plf.ops.CCNOT(wires=[1, 4, 2]),
            plf.ops.CCNOT(wires=[1, 4, 0]).inv(),
            plf.ops.CCNOT(wires=[1, 4, 0]),
        ]

        for converted, expected in zip(rec.queue, expected_queue):
            assert converted.name == expected.name
            assert converted.wires == expected.wires
            assert converted.params == expected.params
예제 #19
0
    def test_gradient(self, theta, phi, varphi, analytic, tol):
        """Test that the gradient works correctly"""
        program = pyquil.Program()

        delta1 = program.declare("delta1", "REAL")
        delta2 = program.declare("delta2", "REAL")
        delta3 = program.declare("delta3", "REAL")

        program += g.RX(delta1, 0)
        program += g.RX(delta2, 1)
        program += g.RX(delta3, 2)
        program += g.CNOT(0, 1)
        program += g.CNOT(1, 2)

        # Convert to a PennyLane circuit
        program_pl = qml.load(program, format="pyquil_program")

        dev = qml.device("default.qubit", wires=3, analytic=analytic)

        @qml.qnode(dev)
        def circuit(params):
            program_pl(parameter_map={
                delta1: params[0],
                delta2: params[1],
                delta3: params[2]
            },
                       wires=range(len(program_pl.defined_qubits)))
            return qml.expval(qml.PauliX(0) @ qml.PauliY(2))

        dcircuit = qml.grad(circuit, 0)
        res = dcircuit([theta, phi, varphi])
        expected = [
            np.cos(theta) * np.sin(phi) * np.sin(varphi),
            np.sin(theta) * np.cos(phi) * np.sin(varphi),
            np.sin(theta) * np.sin(phi) * np.cos(varphi)
        ]

        assert np.allclose(res, expected, tol)
예제 #20
0
    def test_convert_program_with_controlled_defpermutationgates(self):
        """Test that a program that uses controlled permutation gates
        is properly converted."""
        program = pyquil.Program()

        expected_matrix = np.eye(4)
        expected_matrix = expected_matrix[:, [1, 0, 3, 2]]

        expected_controlled_matrix = np.eye(8)
        expected_controlled_matrix[4:, 4:] = expected_matrix

        x_plus_x_definition = pyquil.quil.DefPermutationGate(
            "X+X", [1, 0, 3, 2])
        X_plus_X = x_plus_x_definition.get_constructor()

        program += x_plus_x_definition

        program += g.CNOT(0, 1)
        program += X_plus_X(0, 1).controlled(2)
        program += X_plus_X(1, 2).controlled(0)
        program += g.CNOT(0, 1)

        with OperationRecorder() as rec:
            load_program(program)(wires=range(3))

        expected_queue = [
            qml.CNOT(wires=[0, 1]),
            qml.QubitUnitary(expected_controlled_matrix, wires=[2, 0, 1]),
            qml.QubitUnitary(expected_controlled_matrix, wires=[0, 1, 2]),
            qml.CNOT(wires=[0, 1]),
        ]

        for converted, expected in zip(rec.queue, expected_queue):
            assert converted.name == expected.name
            assert converted.wires == expected.wires
            assert np.array_equal(converted.data, expected.data)
예제 #21
0
    def test_convert_program_with_controlled_defgates(self, tol):
        """Test that a program with controlled defined gates is properly
        converted."""
        program = pyquil.Program()

        sqrt_x = np.array([[0.5 + 0.5j, 0.5 - 0.5j], [0.5 - 0.5j, 0.5 + 0.5j]])
        sqrt_x_t2 = np.kron(sqrt_x, sqrt_x)

        c_sqrt_x = np.eye(4, dtype=complex)
        c_sqrt_x[2:, 2:] = sqrt_x

        c_sqrt_x_t2 = np.eye(8, dtype=complex)
        c_sqrt_x_t2[4:, 4:] = sqrt_x_t2

        sqrt_x_definition = pyquil.quil.DefGate("SQRT-X", sqrt_x)
        SQRT_X = sqrt_x_definition.get_constructor()
        sqrt_x_t2_definition = pyquil.quil.DefGate("SQRT-X-T2", sqrt_x_t2)
        SQRT_X_T2 = sqrt_x_t2_definition.get_constructor()

        program += sqrt_x_definition
        program += sqrt_x_t2_definition

        program += g.CNOT(0, 1)
        program += SQRT_X(0).controlled(1)
        program += SQRT_X_T2(1, 2).controlled(0)
        program += g.X(0).controlled(1)
        program += g.RX(0.4, 0)

        with OperationRecorder() as rec:
            load_program(program)(wires=range(3))

        expected_queue = [
            qml.CNOT(wires=[0, 1]),
            qml.QubitUnitary(c_sqrt_x, wires=[1, 0]),
            qml.QubitUnitary(c_sqrt_x_t2, wires=[0, 1, 2]),
            qml.CNOT(wires=[1, 0]),
            qml.RX(0.4, wires=[0]),
        ]

        for converted, expected in zip(rec.queue, expected_queue):
            assert converted.name == expected.name
            assert converted.wires == expected.wires
            assert np.allclose(converted.params,
                               expected.params,
                               atol=tol,
                               rtol=0)
예제 #22
0
    def test_parameter_not_given_error(self):
        """Test that the correct error is raised if a parameter is not given."""
        program = pyquil.Program()

        alpha = program.declare("alpha", "REAL")
        beta = program.declare("beta", "REAL")

        program += g.H(0)
        program += g.CNOT(0, 1)
        program += g.RX(alpha, 1)
        program += g.RZ(beta, 1)

        a = 0.1

        parameter_map = {"alpha": a}

        with pytest.raises(
                qml.DeviceError,
                match=
                "The PyQuil program defines a variable .* that is not present in the given variable map",
        ):
            load_program(program)(wires=range(2), parameter_map=parameter_map)
예제 #23
0
    def test_default_gates(self):
        # Create qlm program
        prog = Program()
        qreg = prog.qalloc(3)

        for op in pygates_1qb:
            prog.apply(op, qreg[0])

        for op in pygates_2qb:
            prog.apply(op, qreg[0], qreg[1])

        prog.apply(CCNOT, qreg[0], qreg[1], qreg[2])

        qlm_circuit = prog.to_circ()
        result = qlm_to_pyquil(qlm_circuit)

        # Create pyquil program
        expected = Prg()
        expected_creg = expected.declare("ro", "BIT", 3)
        for op in quil_1qb:
            expected += op(0)
        for op in quil_params:
            expected += op(3.14, 0)

        expected += pg.SWAP(0, 1)
        expected += pg.CNOT(0, 1)
        for op in quil_ctrl:
            expected += op(1).controlled(0)
        for op in quil_ctrl_prm:
            expected += op(3.14, 1).controlled(0)
        expected += pg.CCNOT(0, 1, 2)
        expected += pg.MEASURE(0, expected_creg[0])
        expected += pg.MEASURE(1, expected_creg[1])
        expected += pg.MEASURE(2, expected_creg[2])

        self.assertEqual(str(result), str(expected))
예제 #24
0
)
from mitiq.utils import _equal

# Cirq Bell circuit.
cirq_qreg = cirq.LineQubit.range(2)
cirq_circuit = cirq.Circuit(cirq.ops.H.on(cirq_qreg[0]),
                            cirq.ops.CNOT.on(*cirq_qreg))

# Qiskit Bell circuit.
qiskit_qreg = qiskit.QuantumRegister(2)
qiskit_circuit = qiskit.QuantumCircuit(qiskit_qreg)
qiskit_circuit.h(qiskit_qreg[0])
qiskit_circuit.cnot(*qiskit_qreg)

# pyQuil Bell circuit.
pyquil_circuit = Program(gates.H(0), gates.CNOT(0, 1))

# Braket Bell circuit.
braket_circuit = BKCircuit([
    Instruction(braket_gates.H(), 0),
    Instruction(braket_gates.CNot(), [0, 1]),
])

circuit_types = {
    "qiskit": qiskit.QuantumCircuit,
    "pyquil": Program,
    "braket": BKCircuit,
}


@noise_scaling_converter
예제 #25
0
# REQUIRES: api key, qvm running in background ("qvm -S" in a linux terminal
# after it is installed. See Rigetti website for download instructions
# https://www.rigetti.com/forest)
qvm = api.QVMConnection()

# =============================================================================
# teleportation circuit
# =============================================================================

# Alice wants to send |1> to Bob
qprog += gates.X(0)

# main circuit
qprog += [
    gates.H(1),
    gates.CNOT(1, 2),
    gates.CNOT(0, 1),
    gates.H(0),
    gates.MEASURE(0, creg[0]),
    gates.MEASURE(1, creg[1])
]

# conditional operations
qprog.if_then(creg[0], gates.Z(2))
qprog.if_then(creg[1], gates.X(2))

# measure qubit three
qprog.measure(2, creg[2])

# =============================================================================
# run the circuit and print the results. Note Bob always measures 1
예제 #26
0
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# ===========================================
# wavelet.py
#
# Doing the wavelet transform in PyQuil.
#
# written by Ryan LaRose <*****@*****.**>
# at Michigan State University 05-17-18
# ===========================================

from pyquil.quil import Program
import pyquil.gates as gates
from pyquil import api

devices = api.get_devices(as_dict=True)
acorn = devices['8Q-Agave']
compiler = api.CompilerConnection(acorn)

qprog = Program()
qprog.inst(gates.H(0), gates.H(1), gates.H(2), gates.CNOT(0, 2),
           gates.CNOT(1, 2))

job_id = compiler.compile_async(qprog)
job = compiler.wait_for_job(job_id)

print(job.compiled_quil())

qvm = api.QVMConnection()
예제 #27
0
class TestProgramConverter:
    """Test that PyQuil Program instances are properly converted."""
    @pytest.mark.parametrize(
        "pyquil_operation,expected_pl_operation",
        [
            (g.I(0), qml.Identity(wires=[0])),
            (g.H(0), qml.Hadamard(0)),
            (g.H(0).dagger(), qml.Hadamard(0).inv()),
            (g.H(0).dagger().dagger(), qml.Hadamard(0).inv().inv()),
            (g.S(0), qml.S(wires=[0])),
            (g.S(0).dagger(), qml.S(wires=[0]).inv()),
            (g.S(0).dagger().dagger(), qml.S(wires=[0]).inv().inv()),
            (g.T(0), qml.T(wires=[0])),
            (g.T(0).dagger(), qml.T(wires=[0]).inv()),
            (g.T(0).dagger().dagger(), qml.T(wires=[0]).inv().inv()),
            (g.X(0), qml.PauliX(0)),
            (g.X(0).dagger(), qml.PauliX(0).inv()),
            (g.X(0).dagger().dagger(), qml.PauliX(0).inv().inv()),
            (g.X(0).controlled(1), qml.CNOT(wires=[1, 0])),
            (g.X(0).controlled(1).dagger(), qml.CNOT(wires=[1, 0]).inv()),
            (g.X(0).controlled(1).dagger().dagger(),
             qml.CNOT(wires=[1, 0]).inv().inv()),
            (g.X(0).controlled(1).controlled(2),
             plf.ops.CCNOT(wires=[2, 1, 0])),
            (g.X(0).controlled(1).controlled(2).dagger(),
             plf.ops.CCNOT(wires=[2, 1, 0]).inv()),
            (
                g.X(0).controlled(1).controlled(2).dagger().dagger(),
                plf.ops.CCNOT(wires=[2, 1, 0]).inv().inv(),
            ),
            (g.Y(0), qml.PauliY(0)),
            (g.Y(0).dagger(), qml.PauliY(0).inv()),
            (g.Y(0).dagger().dagger(), qml.PauliY(0).inv().inv()),
            (g.Z(0), qml.PauliZ(0)),
            (g.Z(0).dagger(), qml.PauliZ(0).inv()),
            (g.Z(0).dagger().dagger(), qml.PauliZ(0).inv().inv()),
            (g.Z(0).controlled(1), qml.CZ(wires=[1, 0])),
            (g.Z(0).controlled(1).dagger(), qml.CZ(wires=[1, 0]).inv()),
            (g.Z(0).controlled(1).dagger().dagger(),
             qml.CZ(wires=[1, 0]).inv().inv()),
            (g.CNOT(0, 1), qml.CNOT(wires=[0, 1])),
            (g.CNOT(0, 1).dagger(), qml.CNOT(wires=[0, 1]).inv()),
            (g.CNOT(0,
                    1).dagger().dagger(), qml.CNOT(wires=[0, 1]).inv().inv()),
            (g.CNOT(0, 1).controlled(2), plf.ops.CCNOT(wires=[2, 0, 1])),
            (g.CNOT(0, 1).controlled(2).dagger(),
             plf.ops.CCNOT(wires=[2, 0, 1]).inv()),
            (
                g.CNOT(0, 1).controlled(2).dagger().dagger(),
                plf.ops.CCNOT(wires=[2, 0, 1]).inv().inv(),
            ),
            (g.SWAP(0, 1), qml.SWAP(wires=[0, 1])),
            (g.SWAP(0, 1).dagger(), qml.SWAP(wires=[0, 1]).inv()),
            (g.SWAP(0,
                    1).dagger().dagger(), qml.SWAP(wires=[0, 1]).inv().inv()),
            (g.SWAP(0, 1).controlled(2), qml.CSWAP(wires=[2, 0, 1])),
            (g.SWAP(0, 1).controlled(2).dagger(),
             qml.CSWAP(wires=[2, 0, 1]).inv()),
            (g.SWAP(0, 1).controlled(2).dagger().dagger(),
             qml.CSWAP(wires=[2, 0, 1]).inv().inv()),
            (g.ISWAP(0, 1), plf.ops.ISWAP(wires=[0, 1])),
            (g.ISWAP(0, 1).dagger(), plf.ops.ISWAP(wires=[0, 1]).inv()),
            (g.ISWAP(0, 1).dagger().dagger(),
             plf.ops.ISWAP(wires=[0, 1]).inv().inv()),
            (g.PSWAP(0.3, 0, 1), plf.ops.PSWAP(0.3, wires=[0, 1])),
            (g.PSWAP(0.3, 0, 1).dagger(), plf.ops.PSWAP(0.3, wires=[0, 1
                                                                    ]).inv()),
            (g.PSWAP(0.3, 0, 1).dagger().dagger(),
             plf.ops.PSWAP(0.3, wires=[0, 1]).inv().inv()),
            (g.CZ(0, 1), qml.CZ(wires=[0, 1])),
            (g.CZ(0, 1).dagger(), qml.CZ(wires=[0, 1]).inv()),
            (g.CZ(0, 1).dagger().dagger(), qml.CZ(wires=[0, 1]).inv().inv()),
            (g.PHASE(0.3, 0), qml.PhaseShift(0.3, wires=[0])),
            (g.PHASE(0.3, 0).dagger(), qml.PhaseShift(0.3, wires=[0]).inv()),
            (g.PHASE(0.3, 0).dagger().dagger(), qml.PhaseShift(
                0.3, wires=[0]).inv().inv()),
            (g.PHASE(0.3, 0).controlled(1), plf.ops.CPHASE(
                0.3, 3, wires=[1, 0])),
            (g.PHASE(0.3, 0).controlled(1).dagger(),
             plf.ops.CPHASE(0.3, 3, wires=[1, 0]).inv()),
            (
                g.PHASE(0.3, 0).controlled(1).dagger().dagger(),
                plf.ops.CPHASE(0.3, 3, wires=[1, 0]).inv().inv(),
            ),
            (g.RX(0.3, 0), qml.RX(0.3, wires=[0])),
            (g.RX(0.3, 0).dagger(), qml.RX(0.3, wires=[0]).inv()),
            (g.RX(0.3, 0).dagger().dagger(), qml.RX(0.3,
                                                    wires=[0]).inv().inv()),
            (g.RX(0.3, 0).controlled(1), qml.CRX(0.3, wires=[1, 0])),
            (g.RX(0.3, 0).controlled(1).dagger(), qml.CRX(0.3,
                                                          wires=[1, 0]).inv()),
            (g.RX(0.3, 0).controlled(1).dagger().dagger(),
             qml.CRX(0.3, wires=[1, 0]).inv().inv()),
            (g.RY(0.3, 0), qml.RY(0.3, wires=[0])),
            (g.RY(0.3, 0).dagger(), qml.RY(0.3, wires=[0]).inv()),
            (g.RY(0.3, 0).dagger().dagger(), qml.RY(0.3,
                                                    wires=[0]).inv().inv()),
            (g.RY(0.3, 0).controlled(1), qml.CRY(0.3, wires=[1, 0])),
            (g.RY(0.3, 0).controlled(1).dagger(), qml.CRY(0.3,
                                                          wires=[1, 0]).inv()),
            (g.RY(0.3, 0).controlled(1).dagger().dagger(),
             qml.CRY(0.3, wires=[1, 0]).inv().inv()),
            (g.RZ(0.3, 0), qml.RZ(0.3, wires=[0])),
            (g.RZ(0.3, 0).dagger(), qml.RZ(0.3, wires=[0]).inv()),
            (g.RZ(0.3, 0).dagger().dagger(), qml.RZ(0.3,
                                                    wires=[0]).inv().inv()),
            (g.RZ(0.3, 0).controlled(1), qml.CRZ(0.3, wires=[1, 0])),
            (g.RZ(0.3, 0).controlled(1).dagger(), qml.CRZ(0.3,
                                                          wires=[1, 0]).inv()),
            (g.RZ(0.3, 0).controlled(1).dagger().dagger(),
             qml.CRZ(0.3, wires=[1, 0]).inv().inv()),
            (g.CPHASE(0.3, 0, 1), plf.ops.CPHASE(0.3, 3, wires=[0, 1])),
            (g.CPHASE(0.3, 0, 1).dagger(), plf.ops.CPHASE(0.3, 3,
                                                          wires=[0, 1]).inv()),
            (
                g.CPHASE(0.3, 0, 1).dagger().dagger(),
                plf.ops.CPHASE(0.3, 3, wires=[0, 1]).inv().inv(),
            ),
            (g.CPHASE00(0.3, 0, 1), plf.ops.CPHASE(0.3, 0, wires=[0, 1])),
            (g.CPHASE00(0.3, 0, 1).dagger(),
             plf.ops.CPHASE(0.3, 0, wires=[0, 1]).inv()),
            (
                g.CPHASE00(0.3, 0, 1).dagger().dagger(),
                plf.ops.CPHASE(0.3, 0, wires=[0, 1]).inv().inv(),
            ),
            (g.CPHASE01(0.3, 0, 1), plf.ops.CPHASE(0.3, 1, wires=[0, 1])),
            (g.CPHASE01(0.3, 0, 1).dagger(),
             plf.ops.CPHASE(0.3, 1, wires=[0, 1]).inv()),
            (
                g.CPHASE01(0.3, 0, 1).dagger().dagger(),
                plf.ops.CPHASE(0.3, 1, wires=[0, 1]).inv().inv(),
            ),
            (g.CPHASE10(0.3, 0, 1), plf.ops.CPHASE(0.3, 2, wires=[0, 1])),
            (g.CPHASE10(0.3, 0, 1).dagger(),
             plf.ops.CPHASE(0.3, 2, wires=[0, 1]).inv()),
            (
                g.CPHASE10(0.3, 0, 1).dagger().dagger(),
                plf.ops.CPHASE(0.3, 2, wires=[0, 1]).inv().inv(),
            ),
            (g.CSWAP(0, 1, 2), qml.CSWAP(wires=[0, 1, 2])),
            (g.CSWAP(0, 1, 2).dagger(), qml.CSWAP(wires=[0, 1, 2]).inv()),
            (g.CSWAP(0, 1, 2).dagger().dagger(),
             qml.CSWAP(wires=[0, 1, 2]).inv().inv()),
            (g.CCNOT(0, 1, 2), plf.ops.CCNOT(wires=[0, 1, 2])),
            (g.CCNOT(0, 1, 2).dagger(), plf.ops.CCNOT(wires=[0, 1, 2]).inv()),
            (g.CCNOT(0, 1, 2).dagger().dagger(),
             plf.ops.CCNOT(wires=[0, 1, 2]).inv().inv()),
        ],
    )
    def test_convert_operation(self, pyquil_operation, expected_pl_operation):
        """Test that single pyquil gates are properly converted."""
        program = pyquil.Program()

        program += pyquil_operation

        with OperationRecorder() as rec:
            loader = load_program(program)
            loader(wires=range(len(loader.defined_qubits)))

        assert rec.queue[0].name == expected_pl_operation.name
        assert rec.queue[0].wires == expected_pl_operation.wires
        assert rec.queue[0].params == expected_pl_operation.params

    def test_convert_simple_program(self):
        """Test that a simple program is properly converted."""
        program = pyquil.Program()

        program += g.H(0)
        program += g.RZ(0.34, 1)
        program += g.CNOT(0, 3)
        program += g.H(2)
        program += g.H(7)
        program += g.X(7)
        program += g.Y(1)
        program += g.RZ(0.34, 1)

        with OperationRecorder() as rec:
            load_program(program)(wires=range(5))

        # The wires should be assigned as
        # 0  1  2  3  7
        # 0  1  2  3  4

        expected_queue = [
            qml.Hadamard(0),
            qml.RZ(0.34, wires=[1]),
            qml.CNOT(wires=[0, 3]),
            qml.Hadamard(2),
            qml.Hadamard(4),
            qml.PauliX(4),
            qml.PauliY(1),
            qml.RZ(0.34, wires=[1]),
        ]

        for converted, expected in zip(rec.queue, expected_queue):
            assert converted.name == expected.name
            assert converted.wires == expected.wires
            assert converted.params == expected.params

    def test_convert_simple_program_with_parameters(self):
        """Test that a simple program with parameters is properly converted."""
        program = pyquil.Program()

        alpha = program.declare("alpha", "REAL")
        beta = program.declare("beta", "REAL")
        gamma = program.declare("gamma", "REAL")

        program += g.H(0)
        program += g.CNOT(0, 1)
        program += g.RX(alpha, 1)
        program += g.RZ(beta, 1)
        program += g.RX(gamma, 1)
        program += g.CNOT(0, 1)
        program += g.H(0)

        a, b, c = 0.1, 0.2, 0.3

        parameter_map = {"alpha": a, "beta": b, "gamma": c}

        with OperationRecorder() as rec:
            load_program(program)(wires=range(2), parameter_map=parameter_map)

        expected_queue = [
            qml.Hadamard(0),
            qml.CNOT(wires=[0, 1]),
            qml.RX(0.1, wires=[1]),
            qml.RZ(0.2, wires=[1]),
            qml.RX(0.3, wires=[1]),
            qml.CNOT(wires=[0, 1]),
            qml.Hadamard(0),
        ]

        for converted, expected in zip(rec.queue, expected_queue):
            assert converted.name == expected.name
            assert converted.wires == expected.wires
            assert converted.params == expected.params

    def test_parameter_not_given_error(self):
        """Test that the correct error is raised if a parameter is not given."""
        program = pyquil.Program()

        alpha = program.declare("alpha", "REAL")
        beta = program.declare("beta", "REAL")

        program += g.H(0)
        program += g.CNOT(0, 1)
        program += g.RX(alpha, 1)
        program += g.RZ(beta, 1)

        a = 0.1

        parameter_map = {"alpha": a}

        with pytest.raises(
                qml.DeviceError,
                match=
                "The PyQuil program defines a variable .* that is not present in the given variable map",
        ):
            load_program(program)(wires=range(2), parameter_map=parameter_map)

    def test_convert_simple_program_with_parameters_mixed_keys(self):
        """Test that a parametrized program is properly converted when
        the variable map contains mixed key types."""
        program = pyquil.Program()

        alpha = program.declare("alpha", "REAL")
        beta = program.declare("beta", "REAL")
        gamma = program.declare("gamma", "REAL")
        delta = program.declare("delta", "REAL")

        program += g.H(0)
        program += g.CNOT(0, 1)
        program += g.RX(alpha, 1)
        program += g.RZ(beta, 1)
        program += g.RX(gamma, 1)
        program += g.CNOT(0, 1)
        program += g.RZ(delta, 0)
        program += g.H(0)

        a, b, c, d = 0.1, 0.2, 0.3, 0.4

        parameter_map = {"alpha": a, beta: b, gamma: c, "delta": d}

        with OperationRecorder() as rec:
            load_program(program)(wires=range(2), parameter_map=parameter_map)

        expected_queue = [
            qml.Hadamard(0),
            qml.CNOT(wires=[0, 1]),
            qml.RX(0.1, wires=[1]),
            qml.RZ(0.2, wires=[1]),
            qml.RX(0.3, wires=[1]),
            qml.CNOT(wires=[0, 1]),
            qml.RZ(0.4, wires=[0]),
            qml.Hadamard(0),
        ]

        for converted, expected in zip(rec.queue, expected_queue):
            assert converted.name == expected.name
            assert converted.wires == expected.wires
            assert converted.params == expected.params

    def test_convert_simple_program_wire_assignment(self):
        """Test that the assignment of qubits to wires works as expected."""
        program = pyquil.Program()

        program += g.H(0)
        program += g.RZ(0.34, 1)
        program += g.CNOT(0, 3)
        program += g.H(2)
        program += g.H(7)
        program += g.X(7)
        program += g.Y(1)
        program += g.RZ(0.34, 1)

        with OperationRecorder() as rec:
            load_program(program)(wires=[3, 6, 4, 9, 1])

        # The wires should be assigned as
        # 0  1  2  3  7
        # 3  6  4  9  1

        expected_queue = [
            qml.Hadamard(3),
            qml.RZ(0.34, wires=[6]),
            qml.CNOT(wires=[3, 9]),
            qml.Hadamard(4),
            qml.Hadamard(1),
            qml.PauliX(1),
            qml.PauliY(6),
            qml.RZ(0.34, wires=[6]),
        ]

        for converted, expected in zip(rec.queue, expected_queue):
            assert converted.name == expected.name
            assert converted.wires == expected.wires
            assert converted.params == expected.params

    @pytest.mark.parametrize("wires", [[0, 1, 2, 3], [4, 5]])
    def test_convert_wire_error(self, wires):
        """Test that the conversion raises an error if the given number 
        of wires doesn't match the number of qubits in the Program."""
        program = pyquil.Program()

        program += g.H(0)
        program += g.H(1)
        program += g.H(2)

        with pytest.raises(
                qml.DeviceError,
                match=
                "The number of given wires does not match the number of qubits in the PyQuil Program",
        ):
            load_program(program)(wires=wires)

    def test_convert_program_with_inverses(self):
        """Test that a program with inverses is properly converted."""
        program = pyquil.Program()

        program += g.H(0)
        program += g.RZ(0.34, 1).dagger()
        program += g.CNOT(0, 3).dagger()
        program += g.H(2)
        program += g.H(7).dagger().dagger()
        program += g.X(7).dagger()
        program += g.X(7)
        program += g.Y(1)
        program += g.RZ(0.34, 1)

        with OperationRecorder() as rec:
            load_program(program)(wires=range(5))

        expected_queue = [
            qml.Hadamard(0),
            qml.RZ(0.34, wires=[1]).inv(),
            qml.CNOT(wires=[0, 3]).inv(),
            qml.Hadamard(2),
            qml.Hadamard(4),
            qml.PauliX(4).inv(),
            qml.PauliX(4),
            qml.PauliY(1),
            qml.RZ(0.34, wires=[1]),
        ]

        for converted, expected in zip(rec.queue, expected_queue):
            assert converted.name == expected.name
            assert converted.wires == expected.wires
            assert converted.params == expected.params

    def test_convert_program_with_controlled_operations(self):
        """Test that a program with controlled operations is properly converted."""
        program = pyquil.Program()

        program += g.RZ(0.34, 1)
        program += g.RY(0.2, 3).controlled(2)
        program += g.RX(0.4, 2).controlled(0)
        program += g.CNOT(1, 4)
        program += g.CNOT(1, 6).controlled(3)
        program += g.X(3).controlled(4).controlled(1)

        with OperationRecorder() as rec:
            load_program(program)(wires=range(6))

        expected_queue = [
            qml.RZ(0.34, wires=[1]),
            qml.CRY(0.2, wires=[2, 3]),
            qml.CRX(0.4, wires=[0, 2]),
            qml.CNOT(wires=[1, 4]),
            plf.ops.CCNOT(wires=[3, 1, 5]),
            plf.ops.CCNOT(wires=[1, 4, 3]),
        ]

        for converted, expected in zip(rec.queue, expected_queue):
            assert converted.name == expected.name
            assert converted.wires == expected.wires
            assert converted.params == expected.params

    def test_convert_program_with_controlled_operations_not_in_pl_core(
            self, tol):
        """Test that a program with controlled operations out of scope of PL core/PLF 
        is properly converted, i.e. the operations are replaced with controlled operations."""
        program = pyquil.Program()

        CS_matrix = np.eye(4, dtype=complex)
        CS_matrix[3, 3] = 1j

        CCT_matrix = np.eye(8, dtype=complex)
        CCT_matrix[7, 7] = np.exp(1j * np.pi / 4)

        program += g.CNOT(0, 1)
        program += g.S(0).controlled(1)
        program += g.S(1).controlled(0)
        program += g.T(0).controlled(1).controlled(2)
        program += g.T(1).controlled(0).controlled(2)
        program += g.T(2).controlled(1).controlled(0)

        with OperationRecorder() as rec:
            load_program(program)(wires=range(3))

        expected_queue = [
            qml.CNOT(wires=[0, 1]),
            qml.QubitUnitary(CS_matrix, wires=[1, 0]),
            qml.QubitUnitary(CS_matrix, wires=[0, 1]),
            qml.QubitUnitary(CCT_matrix, wires=[2, 1, 0]),
            qml.QubitUnitary(CCT_matrix, wires=[2, 0, 1]),
            qml.QubitUnitary(CCT_matrix, wires=[0, 1, 2]),
        ]

        for converted, expected in zip(rec.queue, expected_queue):
            assert converted.name == expected.name
            assert converted.wires == expected.wires
            assert np.allclose(converted.params,
                               expected.params,
                               atol=tol,
                               rtol=0)

    def test_convert_program_with_controlled_dagger_operations(self):
        """Test that a program that combines controlled and daggered operations
        is properly converted."""
        program = pyquil.Program()

        program += g.CNOT(0, 1).controlled(2)
        program += g.CNOT(0, 1).dagger().controlled(2)
        program += g.CNOT(0, 1).controlled(2).dagger()
        program += g.CNOT(0, 1).dagger().controlled(2).dagger()
        program += g.RX(0.3, 3).controlled(4)
        program += g.RX(0.2, 3).controlled(4).dagger()
        program += g.RX(0.3, 3).dagger().controlled(4)
        program += g.RX(0.2, 3).dagger().controlled(4).dagger()
        program += g.X(2).dagger().controlled(4).controlled(1).dagger()
        program += g.X(0).dagger().controlled(4).controlled(1)
        program += g.X(0).dagger().controlled(4).dagger().dagger().controlled(
            1).dagger()

        with OperationRecorder() as rec:
            load_program(program)(wires=range(5))

        expected_queue = [
            plf.ops.CCNOT(wires=[2, 0, 1]),
            plf.ops.CCNOT(wires=[2, 0, 1]).inv(),
            plf.ops.CCNOT(wires=[2, 0, 1]).inv(),
            plf.ops.CCNOT(wires=[2, 0, 1]),
            qml.CRX(0.3, wires=[4, 3]),
            qml.CRX(0.2, wires=[4, 3]).inv(),
            qml.CRX(0.3, wires=[4, 3]).inv(),
            qml.CRX(0.2, wires=[4, 3]),
            plf.ops.CCNOT(wires=[1, 4, 2]),
            plf.ops.CCNOT(wires=[1, 4, 0]).inv(),
            plf.ops.CCNOT(wires=[1, 4, 0]),
        ]

        for converted, expected in zip(rec.queue, expected_queue):
            assert converted.name == expected.name
            assert converted.wires == expected.wires
            assert converted.params == expected.params

    def test_convert_program_with_defgates(self):
        """Test that a program that defines its own gates is properly converted."""
        program = pyquil.Program()

        sqrt_x = np.array([[0.5 + 0.5j, 0.5 - 0.5j], [0.5 - 0.5j, 0.5 + 0.5j]])

        sqrt_x_t2 = np.kron(sqrt_x, sqrt_x)
        sqrt_x_t3 = np.kron(sqrt_x, sqrt_x_t2)

        sqrt_x_definition = pyquil.quil.DefGate("SQRT-X", sqrt_x)
        SQRT_X = sqrt_x_definition.get_constructor()
        sqrt_x_t2_definition = pyquil.quil.DefGate("SQRT-X-T2", sqrt_x_t2)
        SQRT_X_T2 = sqrt_x_t2_definition.get_constructor()
        sqrt_x_t3_definition = pyquil.quil.DefGate("SQRT-X-T3", sqrt_x_t3)
        SQRT_X_T3 = sqrt_x_t3_definition.get_constructor()

        program += sqrt_x_definition
        program += sqrt_x_t2_definition
        program += sqrt_x_t3_definition

        program += g.CNOT(0, 1)
        program += SQRT_X(0)
        program += SQRT_X_T2(1, 2)
        program += SQRT_X_T3(1, 0, 2)
        program += g.CNOT(0, 1)
        program += g.CNOT(1, 2)
        program += g.CNOT(2, 0)

        with OperationRecorder() as rec:
            load_program(program)(wires=range(3))

        expected_queue = [
            qml.CNOT(wires=[0, 1]),
            qml.QubitUnitary(sqrt_x, wires=[0]),
            qml.QubitUnitary(sqrt_x_t2, wires=[1, 2]),
            qml.QubitUnitary(sqrt_x_t3, wires=[1, 0, 2]),
            qml.CNOT(wires=[0, 1]),
            qml.CNOT(wires=[1, 2]),
            qml.CNOT(wires=[2, 0]),
        ]

        for converted, expected in zip(rec.queue, expected_queue):
            assert converted.name == expected.name
            assert converted.wires == expected.wires
            assert converted.params == expected.params

    def test_convert_program_with_controlled_defgates(self, tol):
        """Test that a program with controlled defined gates is properly
        converted."""
        program = pyquil.Program()

        sqrt_x = np.array([[0.5 + 0.5j, 0.5 - 0.5j], [0.5 - 0.5j, 0.5 + 0.5j]])
        sqrt_x_t2 = np.kron(sqrt_x, sqrt_x)

        c_sqrt_x = np.eye(4, dtype=complex)
        c_sqrt_x[2:, 2:] = sqrt_x

        c_sqrt_x_t2 = np.eye(8, dtype=complex)
        c_sqrt_x_t2[4:, 4:] = sqrt_x_t2

        sqrt_x_definition = pyquil.quil.DefGate("SQRT-X", sqrt_x)
        SQRT_X = sqrt_x_definition.get_constructor()
        sqrt_x_t2_definition = pyquil.quil.DefGate("SQRT-X-T2", sqrt_x_t2)
        SQRT_X_T2 = sqrt_x_t2_definition.get_constructor()

        program += sqrt_x_definition
        program += sqrt_x_t2_definition

        program += g.CNOT(0, 1)
        program += SQRT_X(0).controlled(1)
        program += SQRT_X_T2(1, 2).controlled(0)
        program += g.X(0).controlled(1)
        program += g.RX(0.4, 0)

        with OperationRecorder() as rec:
            load_program(program)(wires=range(3))

        expected_queue = [
            qml.CNOT(wires=[0, 1]),
            qml.QubitUnitary(c_sqrt_x, wires=[1, 0]),
            qml.QubitUnitary(c_sqrt_x_t2, wires=[0, 1, 2]),
            qml.CNOT(wires=[1, 0]),
            qml.RX(0.4, wires=[0]),
        ]

        for converted, expected in zip(rec.queue, expected_queue):
            assert converted.name == expected.name
            assert converted.wires == expected.wires
            assert np.allclose(converted.params,
                               expected.params,
                               atol=tol,
                               rtol=0)

    def test_convert_program_with_defpermutationgates(self):
        """Test that a program with gates defined via DefPermutationGate is 
        properly converted."""
        program = pyquil.Program()

        expected_matrix = np.eye(4)
        expected_matrix = expected_matrix[:, [1, 0, 3, 2]]

        x_plus_x_definition = pyquil.quil.DefPermutationGate(
            "X+X", [1, 0, 3, 2])
        X_plus_X = x_plus_x_definition.get_constructor()

        program += x_plus_x_definition

        program += g.CNOT(0, 1)
        program += X_plus_X(0, 1)
        program += g.CNOT(0, 1)

        with OperationRecorder() as rec:
            load_program(program)(wires=range(2))

        expected_queue = [
            qml.CNOT(wires=[0, 1]),
            qml.QubitUnitary(expected_matrix, wires=[0, 1]),
            qml.CNOT(wires=[0, 1]),
        ]

        for converted, expected in zip(rec.queue, expected_queue):
            assert converted.name == expected.name
            assert converted.wires == expected.wires
            assert np.array_equal(converted.params, expected.params)

    def test_convert_program_with_controlled_defpermutationgates(self):
        """Test that a program that uses controlled permutation gates 
        is properly converted."""
        program = pyquil.Program()

        expected_matrix = np.eye(4)
        expected_matrix = expected_matrix[:, [1, 0, 3, 2]]

        expected_controlled_matrix = np.eye(8)
        expected_controlled_matrix[4:, 4:] = expected_matrix

        x_plus_x_definition = pyquil.quil.DefPermutationGate(
            "X+X", [1, 0, 3, 2])
        X_plus_X = x_plus_x_definition.get_constructor()

        program += x_plus_x_definition

        program += g.CNOT(0, 1)
        program += X_plus_X(0, 1).controlled(2)
        program += X_plus_X(1, 2).controlled(0)
        program += g.CNOT(0, 1)

        with OperationRecorder() as rec:
            load_program(program)(wires=range(3))

        expected_queue = [
            qml.CNOT(wires=[0, 1]),
            qml.QubitUnitary(expected_controlled_matrix, wires=[2, 0, 1]),
            qml.QubitUnitary(expected_controlled_matrix, wires=[0, 1, 2]),
            qml.CNOT(wires=[0, 1]),
        ]

        for converted, expected in zip(rec.queue, expected_queue):
            assert converted.name == expected.name
            assert converted.wires == expected.wires
            assert np.array_equal(converted.params, expected.params)

    def test_forked_gate_error(self):
        """Test that an error is raised if conversion of a 
        forked gate is attempted."""
        program = pyquil.Program()

        program += g.CNOT(0, 1)
        program += g.RX(0.3, 1).forked(2, [0.5])
        program += g.CNOT(0, 1)

        with pytest.raises(
                qml.DeviceError,
                match=
                "Forked gates can not be imported into PennyLane, as this functionality is not supported",
        ):
            load_program(program)(wires=range(3))
예제 #28
0
def CNOT(qubit1, qubit2) -> None:
    program_context().inst(gates.CNOT(qubit1, qubit2))
예제 #29
0
    depth = 10

# allocate classical memory
creg = qprog.declare("ro", memory_size=n)

# =============================================================================
# circuit to test simulator
# =============================================================================

# main (arbitrary) circuit
for level in range(depth):
    for ii in range(n):
        qprog.inst(gates.H(ii),
                   gates.X(ii))
        if ii != 0:
            qprog.inst(gates.CNOT(ii, 0))
            
# measurements
for ii in range(n):
    qprog.inst(gates.MEASURE(ii, creg[ii]))

# =============================================================================
# run the circuit and print the results
# =============================================================================
    
# timing -- get the start time
start = time.time()

output = qvm.run(qprog)

# timing -- get the end time