Beispiel #1
0
    def test_compile_mixed_tape_qfunc_transform(self):
        """Test that we can interchange tape and qfunc transforms."""

        wires = [0, 1, 2]
        qfunc = build_qfunc(wires)
        dev = qml.device("default.qubit", wires=wires)

        pipeline = [
            commute_controlled(direction="right").tape_fn,
            cancel_inverses,
            merge_rotations().tape_fn,
        ]

        transformed_qfunc = compile(pipeline=pipeline)(qfunc)
        transformed_qnode = qml.QNode(transformed_qfunc, dev)
        transformed_result = transformed_qnode(0.3, 0.4, 0.5)

        names_expected = ["Hadamard", "CNOT", "RX", "CY", "PauliY"]
        wires_expected = [
            Wires(wires[0]),
            Wires([wires[2], wires[1]]),
            Wires(wires[0]),
            Wires([wires[1], wires[2]]),
            Wires(wires[2]),
        ]

        compare_operation_lists(transformed_qnode.qtape.operations, names_expected, wires_expected)
Beispiel #2
0
    def test_compile_pipeline_with_non_default_arguments(self, wires):
        """Test that using non-default arguments returns the correct results."""

        qfunc = build_qfunc(wires)
        dev = qml.device("default.qubit", wires=Wires(wires))

        qnode = qml.QNode(qfunc, dev)

        pipeline = [
            commute_controlled(direction="left"),
            cancel_inverses,
            merge_rotations(atol=1e-6),
        ]

        transformed_qfunc = compile(pipeline=pipeline)(qfunc)
        transformed_qnode = qml.QNode(transformed_qfunc, dev)

        original_result = qnode(0.3, 0.4, 0.5)
        transformed_result = transformed_qnode(0.3, 0.4, 0.5)
        assert np.allclose(original_result, transformed_result)

        names_expected = ["Hadamard", "CNOT", "RX", "PauliY", "CY"]
        wires_expected = [
            Wires(wires[0]),
            Wires([wires[2], wires[1]]),
            Wires(wires[0]),
            Wires(wires[2]),
            Wires([wires[1], wires[2]]),
        ]

        compare_operation_lists(transformed_qnode.qtape.operations, names_expected, wires_expected)
Beispiel #3
0
    def test_two_qubits_rotation_merge_tolerance(self):
        """Test whether tolerance argument is respected for merging."""
        def qfunc():
            qml.RZ(1e-7, wires=0)
            qml.RZ(-2e-7, wires=0)

        # Try with default tolerance; these ops should still be applied
        transformed_qfunc = merge_rotations()(qfunc)

        ops = qml.transforms.make_tape(transformed_qfunc)().operations

        assert len(ops) == 1
        assert ops[0].name == "RZ"
        assert ops[0].parameters[0] == -1e-7

        # Now try with higher tolerance threshold; the ops should cancel
        transformed_qfunc = merge_rotations(atol=1e-5)(qfunc)
        ops = qml.transforms.make_tape(transformed_qfunc)().operations
        assert len(ops) == 0
Beispiel #4
0
    def test_controlled_rotation_merge(self, theta_1, theta_2, expected_ops):
        """Test that adjacent controlled rotations on the same wires in same order get merged."""
        def qfunc():
            qml.CRY(theta_1, wires=["w1", "w2"])
            qml.CRY(theta_2, wires=["w1", "w2"])

        transformed_qfunc = merge_rotations()(qfunc)

        ops = qml.transforms.make_tape(transformed_qfunc)().operations

        assert len(ops) == len(expected_ops)

        # Check that all operations and parameter values are as expected
        for op_obtained, op_expected in zip(ops, expected_ops):
            assert op_obtained.name == op_expected.name
            assert np.allclose(op_obtained.parameters, op_expected.parameters)
Beispiel #5
0
    def test_controlled_rotation_no_merge(self):
        """Test that adjacent controlled rotations on the same wires in different order don't merge."""
        def qfunc():
            qml.CRX(0.2, wires=["w1", "w2"])
            qml.CRX(0.3, wires=["w2", "w1"])

        transformed_qfunc = merge_rotations()(qfunc)

        ops = qml.transforms.make_tape(transformed_qfunc)().operations

        names_expected = ["CRX", "CRX"]
        wires_expected = [Wires(["w1", "w2"]), Wires(["w2", "w1"])]
        compare_operation_lists(ops, names_expected, wires_expected)

        assert ops[0].parameters[0] == 0.2
        assert ops[1].parameters[0] == 0.3
Beispiel #6
0
    def test_two_qubits_rotation_no_merge(self, theta_1, theta_2,
                                          expected_ops):
        """Test that a two-qubit circuit with rotations on different qubits
        do not get merged."""
        def qfunc():
            qml.RZ(theta_1, wires=0)
            qml.RZ(theta_2, wires=1)

        transformed_qfunc = merge_rotations()(qfunc)

        ops = qml.transforms.make_tape(transformed_qfunc)().operations

        assert len(ops) == len(expected_ops)

        for op_obtained, op_expected in zip(ops, expected_ops):
            assert op_obtained.name == op_expected.name
            assert np.allclose(op_obtained.parameters, op_expected.parameters)
Beispiel #7
0
    def test_one_qubit_rotation_merge(self, theta_1, theta_2, expected_ops):
        """Test that a single-qubit circuit with adjacent rotation along the same
        axis either merge, or cancel if the angles sum to 0."""
        def qfunc():
            qml.RZ(theta_1, wires=0)
            qml.RZ(theta_2, wires=0)

        transformed_qfunc = merge_rotations()(qfunc)

        ops = qml.transforms.make_tape(transformed_qfunc)().operations

        assert len(ops) == len(expected_ops)

        # Check that all operations and parameter values are as expected
        for op_obtained, op_expected in zip(ops, expected_ops):
            assert op_obtained.name == op_expected.name
            assert np.allclose(op_obtained.parameters, op_expected.parameters)
Beispiel #8
0
    def test_one_qubit_rotation_blocked(self):
        """Test that rotations on one-qubit separated by a "blocking" operation don't merge."""
        def qfunc():
            qml.RX(0.5, wires=0)
            qml.Hadamard(wires=0)
            qml.RX(0.4, wires=0)

        transformed_qfunc = merge_rotations()(qfunc)

        ops = qml.transforms.make_tape(transformed_qfunc)().operations

        names_expected = ["RX", "Hadamard", "RX"]
        wires_expected = [Wires(0)] * 3
        compare_operation_lists(ops, names_expected, wires_expected)

        assert ops[0].parameters[0] == 0.5
        assert ops[2].parameters[0] == 0.4
Beispiel #9
0
    def test_two_qubits_rotation_blocked(self):
        """Test that rotations on a two-qubit system separated by a "blocking" operation
        don't merge."""
        def qfunc():
            qml.RX(-0.42, wires=0)
            qml.CNOT(wires=[0, 1])
            qml.RX(0.8, wires=0)

        transformed_qfunc = merge_rotations()(qfunc)

        ops = qml.transforms.make_tape(transformed_qfunc)().operations

        names_expected = ["RX", "CNOT", "RX"]
        wires_expected = [Wires(0), Wires([0, 1]), Wires(0)]
        compare_operation_lists(ops, names_expected, wires_expected)

        assert ops[0].parameters[0] == -0.42
        assert ops[2].parameters[0] == 0.8
Beispiel #10
0
    def test_two_qubits_merge_with_adjoint(self, theta_11, theta_12, theta_21,
                                           theta_22, expected_ops):
        """Test that adjoint rotations on different qubits get merged."""
        def qfunc():
            qml.CRX(theta_11, wires=[0, 1])
            qml.adjoint(qml.RY)(theta_21, wires=2)
            qml.adjoint(qml.CRX)(theta_12, wires=[0, 1])
            qml.RY(theta_22, wires=2)

        transformed_qfunc = merge_rotations()(qfunc)

        ops = qml.transforms.make_tape(transformed_qfunc)().operations

        assert len(ops) == len(expected_ops)

        for op_obtained, op_expected in zip(ops, expected_ops):
            assert op_obtained.name == op_expected.name
            assert np.allclose(op_obtained.parameters, op_expected.parameters)
Beispiel #11
0
    def test_two_qubits_merge_gate_subset(self):
        """Test that specifying a subset of operations to include merges correctly."""
        def qfunc():
            qml.CRX(0.1, wires=[0, 1])
            qml.CRX(0.2, wires=[0, 1])
            qml.RY(0.3, wires=["a"])
            qml.RY(0.5, wires=["a"])
            qml.RX(-0.5, wires=[2])
            qml.RX(0.2, wires=[2])

        transformed_qfunc = merge_rotations(include_gates=["RX", "CRX"])(qfunc)

        ops = qml.transforms.make_tape(transformed_qfunc)().operations

        names_expected = ["CRX", "RY", "RY", "RX"]
        wires_expected = [Wires([0, 1]), Wires("a"), Wires("a"), Wires(2)]
        compare_operation_lists(ops, names_expected, wires_expected)

        assert qml.math.isclose(ops[0].parameters[0], 0.3)
        assert qml.math.isclose(ops[1].parameters[0], 0.3)
        assert qml.math.isclose(ops[2].parameters[0], 0.5)
        assert qml.math.isclose(ops[3].parameters[0], -0.3)
Beispiel #12
0
def qfunc(theta):
    qml.Hadamard(wires=0)
    qml.RZ(theta[0], wires=0)
    qml.PauliY(wires=1)
    qml.RZ(theta[1], wires=0)
    qml.CNOT(wires=[1, 2])
    qml.CRY(theta[2], wires=[1, 2])
    qml.PauliZ(wires=0)
    qml.CRY(theta[3], wires=[1, 2])
    qml.Rot(theta[0], theta[1], theta[2], wires=1)
    qml.Rot(theta[2], theta[3], theta[0], wires=1)
    qml.Rot(0.0, 0.0, 0.0, wires=1)
    return qml.expval(qml.PauliX(0) @ qml.PauliX(2))


transformed_qfunc = merge_rotations()(qfunc)

expected_op_list = ["Hadamard", "RZ", "PauliY", "CNOT", "CRY", "PauliZ", "Rot"]
expected_wires_list = [
    Wires(0),
    Wires(0),
    Wires(1),
    Wires([1, 2]),
    Wires([1, 2]),
    Wires(0),
    Wires(1),
]


class TestMergeRotationsInterfaces:
    """Test that rotation merging works in all interfaces."""