def test_push_x_gates_right(self):
        """Test that X-basis gates before controlled-X-type gates on targets get pushed ahead."""
        def qfunc():
            qml.PauliX(wires=2)
            qml.CNOT(wires=[0, 2])
            qml.RX(0.2, wires=2)
            qml.Toffoli(wires=[0, 1, 2])
            qml.SX(wires=1)
            qml.PauliX(wires=1)
            qml.CRX(0.1, wires=[0, 1])

        transformed_qfunc = commute_controlled()(qfunc)

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

        names_expected = [
            "CNOT", "Toffoli", "PauliX", "RX", "CRX", "SX", "PauliX"
        ]
        wires_expected = [
            Wires([0, 2]),
            Wires([0, 1, 2]),
            Wires(2),
            Wires(2),
            Wires([0, 1]),
            Wires(1),
            Wires(1),
        ]
        compare_operation_lists(ops, names_expected, wires_expected)
    def test_push_z_gates_left(self):
        """Test that Z-basis after before controlled-Z-type gates on controls *and*
        targets get pushed behind."""
        def qfunc():
            qml.CZ(wires=[0, 2])
            qml.PauliZ(wires=2)
            qml.S(wires=0)

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

            qml.CRZ(0.5, wires=[0, 1])
            qml.RZ(0.2, wires=2)
            qml.T(wires=0)
            qml.PauliZ(wires=0)

        transformed_qfunc = commute_controlled(direction="left")(qfunc)

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

        names_expected = [
            "PauliZ", "S", "RZ", "T", "PauliZ", "CZ", "CNOT", "CRZ"
        ]
        wires_expected = [
            Wires(2),
            Wires(0),
            Wires(2),
            Wires(0),
            Wires(0),
            Wires([0, 2])
        ] + [Wires([0, 1])] * 2

        compare_operation_lists(ops, names_expected, wires_expected)
Пример #3
0
    def test_push_mixed_with_matrix(self, direction):
        """Test that arbitrary gates after controlled gates on controls *and*
        targets get properly pushed."""
        def qfunc():
            qml.PauliX(wires=1)
            qml.S(wires=0)
            qml.CZ(wires=[0, 1])
            qml.CNOT(wires=[1, 0])
            qml.PauliY(wires=1)
            qml.CRY(0.5, wires=[1, 0])
            qml.PhaseShift(0.2, wires=0)
            qml.PauliY(wires=1)
            qml.T(wires=0)
            qml.CRZ(-0.3, wires=[0, 1])
            qml.RZ(0.2, wires=0)
            qml.PauliZ(wires=0)
            qml.PauliX(wires=1)
            qml.CRY(0.2, wires=[1, 0])

        transformed_qfunc = commute_controlled()(qfunc)

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

        assert len(original_ops) == len(transformed_ops)

        # Compare matrices
        matrix_expected = compute_matrix_from_ops_two_qubit(original_ops,
                                                            wire_order=[0, 1])
        matrix_obtained = compute_matrix_from_ops_two_qubit(transformed_ops,
                                                            wire_order=[0, 1])
        assert check_matrix_equivalence(matrix_expected, matrix_obtained)
    def test_push_z_gates_right(self):
        """Test that Z-basis gates before controlled-Z-type gates on controls *and* targets get pushed ahead."""
        def qfunc():
            qml.PauliZ(wires=2)
            qml.S(wires=0)
            qml.CZ(wires=[0, 2])

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

            qml.PhaseShift(0.2, wires=2)
            qml.T(wires=0)
            qml.PauliZ(wires=0)
            qml.CRZ(0.5, wires=[0, 1])

        transformed_qfunc = commute_controlled()(qfunc)

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

        names_expected = [
            "CZ", "PauliZ", "CNOT", "PhaseShift", "CRZ", "S", "T", "PauliZ"
        ]
        wires_expected = (
            [Wires([0, 2]), Wires(2),
             Wires([0, 1]), Wires(2)] + [Wires([0, 1])] + [Wires(0)] * 3)

        compare_operation_lists(ops, names_expected, wires_expected)
Пример #5
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)
Пример #6
0
    def test_compile_multiple_passes(self, wires):
        """Test that running multiple passes produces the correct results."""

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

        qnode = qml.QNode(qfunc, dev)

        # Rotation merging will not occur at all until commuting gates are
        # pushed through
        pipeline = [merge_rotations, commute_controlled(direction="left"), cancel_inverses]

        transformed_qfunc = compile(pipeline=pipeline, num_passes=2)(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)
Пример #7
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)
Пример #8
0
    def test_compile_decompose_into_basis_gates(self, wires):
        """Test that running multiple passes produces 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
        ]

        basis_set = ["CNOT", "RX", "RY", "RZ"]

        transformed_qfunc = compile(pipeline=pipeline,
                                    basis_set=basis_set)(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 = [
            "RZ",
            "RX",
            "RZ",
            "RZ",
            "CNOT",
            "RX",
            "RZ",
            "RY",
            "RZ",
            "RY",
            "CNOT",
            "RY",
            "CNOT",
        ]

        wires_expected = [
            Wires(wires[0]),
            Wires(wires[0]),
            Wires(wires[0]),
            Wires(wires[2]),
            Wires([wires[2], wires[1]]),
            Wires(wires[0]),
            Wires(wires[1]),
            Wires(wires[2]),
            Wires(wires[2]),
            Wires(wires[2]),
            Wires([wires[1], wires[2]]),
            Wires(wires[2]),
            Wires([wires[1], wires[2]]),
        ]

        compare_operation_lists(transformed_qnode.qtape.operations,
                                names_expected, wires_expected)
    def test_invalid_direction(self):
        """Test that any direction other than 'left' or 'right' raises an error."""
        def qfunc():
            qml.PauliX(wires=2)
            qml.CNOT(wires=[0, 2])
            qml.RX(0.2, wires=2)

        transformed_qfunc = commute_controlled(direction="sideways")(qfunc)

        with pytest.raises(ValueError, match="must be 'left' or 'right'"):
            ops = qml.transforms.make_tape(transformed_qfunc)().operations
Пример #10
0
    def test_gate_blocked_different_basis(self, direction):
        """Test that gates do not get pushed through controlled gates whose target bases don't match."""
        def qfunc():
            qml.PauliZ(wires="b")
            qml.CNOT(wires=[2, "b"])
            qml.PauliY(wires="b")

        transformed_qfunc = commute_controlled(direction=direction)(qfunc)

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

        names_expected = ["PauliZ", "CNOT", "PauliY"]
        wires_expected = [Wires("b"), Wires([2, "b"]), Wires("b")]
        compare_operation_lists(ops, names_expected, wires_expected)
Пример #11
0
    def test_gate_with_no_basis(self, direction):
        """Test that gates with no basis specified are ignored."""
        def qfunc():
            qml.PauliX(wires=2)
            qml.ControlledQubitUnitary(np.array([[0, 1], [1, 0]]),
                                       control_wires=0,
                                       wires=2)
            qml.PauliX(wires=2)

        transformed_qfunc = commute_controlled(direction=direction)(qfunc)

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

        names_expected = ["PauliX", "ControlledQubitUnitary", "PauliX"]
        wires_expected = [Wires(2), Wires([0, 2]), Wires(2)]
        compare_operation_lists(ops, names_expected, wires_expected)
    def test_dont_push_x_gates(self, direction):
        """Test that X-basis gates before controlled-X-type gates on controls don't get pushed."""
        def qfunc():
            qml.PauliX(wires="a")
            qml.CNOT(wires=["a", "c"])
            qml.RX(0.2, wires="a")
            qml.Toffoli(wires=["c", "a", "b"])

        transformed_qfunc = commute_controlled(direction=direction)(qfunc)

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

        names_expected = ["PauliX", "CNOT", "RX", "Toffoli"]
        wires_expected = [
            Wires("a"),
            Wires(["a", "c"]),
            Wires("a"),
            Wires(["c", "a", "b"])
        ]
        compare_operation_lists(ops, names_expected, wires_expected)
    def test_dont_push_y_gates(self, direction):
        """Test that Y-basis gates next to controlled-Y-type gates on controls don't get pushed."""
        def qfunc():
            qml.CRY(-0.2, wires=["a", 2])
            qml.PauliY(wires="a")
            qml.CNOT(wires=[1, 2])
            qml.CY(wires=["a", 1])
            qml.RY(0.3, wires="a")

        transformed_qfunc = commute_controlled()(qfunc)

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

        names_expected = ["CRY", "PauliY", "CNOT", "CY", "RY"]
        wires_expected = [
            Wires(["a", 2]),
            Wires("a"),
            Wires([1, 2]),
            Wires(["a", 1]),
            Wires("a")
        ]
        compare_operation_lists(ops, names_expected, wires_expected)
    def test_push_y_gates_left(self):
        """Test that Y-basis gates after controlled-Y-type gates on targets get pushed behind."""
        def qfunc():
            qml.CRY(-0.5, wires=["a", 2])
            qml.PauliY(wires=2)
            qml.CNOT(wires=[1, 2])
            qml.CY(wires=["a", 1])
            qml.RY(0.3, wires=1)

        transformed_qfunc = commute_controlled(direction="left")(qfunc)

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

        names_expected = ["PauliY", "CRY", "CNOT", "RY", "CY"]
        wires_expected = [
            Wires(2),
            Wires(["a", 2]),
            Wires([1, 2]),
            Wires(1),
            Wires(["a", 1])
        ]
        compare_operation_lists(ops, names_expected, wires_expected)
dev = qml.device("default.qubit", wires=3)


def qfunc(theta):
    qml.PauliX(wires=2)
    qml.S(wires=0)
    qml.CNOT(wires=[0, 1])
    qml.PauliY(wires=1)
    qml.CRY(theta[0], wires=[2, 1])
    qml.PhaseShift(theta[1], wires=0)
    qml.T(wires=0)
    qml.Toffoli(wires=[0, 1, 2])
    return qml.expval(qml.PauliZ(0))


transformed_qfunc = commute_controlled()(qfunc)

expected_op_list = [
    "PauliX", "CNOT", "CRY", "PauliY", "Toffoli", "S", "PhaseShift", "T"
]
expected_wires_list = [
    Wires(2),
    Wires([0, 1]),
    Wires([2, 1]),
    Wires(1),
    Wires([0, 1, 2]),
    Wires(0),
    Wires(0),
    Wires(0),
]
Пример #16
0
            Wires(1),
            Wires([1, 2]),
            Wires(2),
            Wires([2, 0]),
        ] * 2

        compare_operation_lists(transformed_qnode.qtape.operations, names_expected, wires_expected)


def qfunc(x, params):
    qml.templates.AngleEmbedding(x, wires=range(3))
    qml.templates.BasicEntanglerLayers(params, wires=range(3))
    return qml.expval(qml.PauliZ(wires=2))


pipeline = [commute_controlled(direction="left"), merge_rotations]

transformed_qfunc = compile(pipeline=pipeline)(qfunc)

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

expected_op_list = ["RX"] * 3 + ["CNOT", "CNOT", "RX", "CNOT", "RX", "RX"] + ["CNOT"] * 3

expected_wires_list = [
    Wires(0),
    Wires(1),
    Wires(2),
    Wires([0, 1]),
    Wires([1, 2]),
    Wires(0),
    Wires([2, 0]),