Example #1
0
    def test_single_qubit_fusion_multiple_qubits(self):
        """Test that all sequences of single-qubit gates across multiple qubits fuse properly."""
        def qfunc():
            qml.RZ(0.3, wires="a")
            qml.RY(0.5, wires="a")
            qml.Rot(0.1, 0.2, 0.3, wires="b")
            qml.RX(0.1, wires="a")
            qml.CNOT(wires=["b", "a"])
            qml.SX(wires="b")
            qml.S(wires="b")
            qml.PhaseShift(0.3, wires="b")

        transformed_qfunc = single_qubit_fusion()(qfunc)

        original_ops = qml.transforms.make_tape(qfunc)().operations
        transformed_ops = qml.transforms.make_tape(
            transformed_qfunc)().operations

        names_expected = ["Rot", "Rot", "CNOT", "Rot"]
        wires_expected = [
            Wires("a"), Wires("b"),
            Wires(["b", "a"]),
            Wires("b")
        ]
        compare_operation_lists(transformed_ops, names_expected,
                                wires_expected)

        # Check matrix representation
        matrix_expected = compute_matrix_from_ops_two_qubit(
            original_ops, ["a", "b"])
        matrix_obtained = compute_matrix_from_ops_two_qubit(
            transformed_ops, ["a", "b"])
        assert check_matrix_equivalence(matrix_expected, matrix_obtained)
Example #2
0
    def test_single_qubit_cancelled_fusion(self):
        """Test if a sequence of single-qubit gates that all cancel yields no operations."""
        def qfunc():
            qml.RZ(0.1, wires=0)
            qml.RX(0.2, wires=0)
            qml.RX(-0.2, wires=0)
            qml.RZ(-0.1, wires=0)

        transformed_qfunc = single_qubit_fusion()(qfunc)
        transformed_ops = qml.transforms.make_tape(
            transformed_qfunc)().operations
        assert len(transformed_ops) == 0
Example #3
0
    def test_single_qubit_fusion_no_gates_after(self):
        """Test that gates with nothing after are applied without modification."""
        def qfunc():
            qml.RZ(0.1, wires=0)
            qml.Hadamard(wires=1)

        transformed_qfunc = single_qubit_fusion()(qfunc)
        transformed_ops = qml.transforms.make_tape(
            transformed_qfunc)().operations

        names_expected = ["RZ", "Hadamard"]
        wires_expected = [Wires(0), Wires(1)]
        compare_operation_lists(transformed_ops, names_expected,
                                wires_expected)
Example #4
0
    def test_single_qubit_fusion_not_implemented(self):
        """Test that fusion is correctly skipped for single-qubit gates where
        the rotation angles are not specified."""
        def qfunc():
            qml.RZ(0.1, wires=0)
            qml.Hadamard(wires=0)
            # No rotation angles specified for PauliRot since it is a gate that
            # in principle acts on an arbitrary number of wires.
            qml.PauliRot(0.2, "X", wires=0)
            qml.RZ(0.1, wires=0)
            qml.Hadamard(wires=0)

        transformed_qfunc = single_qubit_fusion()(qfunc)
        transformed_ops = qml.transforms.make_tape(
            transformed_qfunc)().operations

        names_expected = ["Rot", "PauliRot", "Rot"]
        wires_expected = [Wires(0)] * 3
        compare_operation_lists(transformed_ops, names_expected,
                                wires_expected)
Example #5
0
    def test_single_qubit_full_fusion(self):
        """Test that a sequence of single-qubit gates all fuse."""
        def qfunc():
            qml.RZ(0.3, wires=0)
            qml.Hadamard(wires=0)
            qml.Rot(0.1, 0.2, 0.3, wires=0)
            qml.RX(0.1, wires=0)
            qml.SX(wires=0)
            qml.T(wires=0)
            qml.PauliX(wires=0)

        transformed_qfunc = single_qubit_fusion()(qfunc)

        # Compare matrices
        compute_matrix = get_unitary_matrix(qfunc, [0])
        matrix_expected = compute_matrix()

        compute_transformed_matrix = get_unitary_matrix(transformed_qfunc, [0])
        matrix_obtained = compute_transformed_matrix()
        assert check_matrix_equivalence(matrix_expected, matrix_obtained)
Example #6
0
    def test_single_qubit_fusion_exclude_gates(self):
        """Test that fusion is correctly skipped for gates explicitly on an
        exclusion list."""
        def qfunc():
            # Excluded gate at the start
            qml.RZ(0.1, wires=0)
            qml.Hadamard(wires=0)
            qml.PauliX(wires=0)
            qml.RZ(0.1, wires=1)
            qml.CNOT(wires=[0, 1])
            qml.Hadamard(wires=0)
            # Excluded gate after another gate
            qml.RZ(0.1, wires=0)
            qml.PauliX(wires=1)
            qml.PauliZ(wires=1)
            # Excluded gate after multiple others
            qml.RZ(0.2, wires=1)

        original_ops = qml.transforms.make_tape(qfunc)().operations

        transformed_qfunc = single_qubit_fusion(exclude_gates=["RZ"])(qfunc)
        transformed_ops = qml.transforms.make_tape(
            transformed_qfunc)().operations

        names_expected = [
            "RZ", "Rot", "RZ", "CNOT", "Hadamard", "RZ", "Rot", "RZ"
        ]
        wires_expected = ([Wires(0)] * 2 + [Wires(1)] + [Wires([0, 1])] +
                          [Wires(0)] * 2 + [Wires(1)] * 2)
        compare_operation_lists(transformed_ops, names_expected,
                                wires_expected)

        # Compare matrices
        compute_matrix = get_unitary_matrix(qfunc, [0, 1])
        matrix_expected = compute_matrix()

        compute_transformed_matrix = get_unitary_matrix(
            transformed_qfunc, [0, 1])
        matrix_obtained = compute_transformed_matrix()
        assert check_matrix_equivalence(matrix_expected, matrix_obtained)
Example #7
0
    def test_single_qubit_full_fusion(self):
        """Test that a sequence of single-qubit gates all fuse."""
        def qfunc():
            qml.RZ(0.3, wires=0)
            qml.Hadamard(wires=0)
            qml.Rot(0.1, 0.2, 0.3, wires=0)
            qml.RX(0.1, wires=0)
            qml.SX(wires=0)
            qml.T(wires=0)
            qml.PauliX(wires=0)

        transformed_qfunc = single_qubit_fusion()(qfunc)

        original_ops = qml.transforms.make_tape(qfunc)().operations
        transformed_ops = qml.transforms.make_tape(
            transformed_qfunc)().operations

        assert len(transformed_ops) == 1

        # Compare matrices
        matrix_expected = compute_matrix_from_ops_one_qubit(original_ops)
        matrix_obtained = compute_matrix_from_ops_one_qubit(transformed_ops)
        assert check_matrix_equivalence(matrix_expected, matrix_obtained)
Example #8
0
# Test each of single-qubit, two-qubit, and Rot gates
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)
    return qml.expval(qml.PauliX(0) @ qml.PauliX(2))


transformed_qfunc = single_qubit_fusion()(qfunc)

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


class TestSingleQubitFusionInterfaces:
    """Test that rotation merging works in all interfaces."""
    def test_single_qubit_fusion_autograd(self):