Exemplo n.º 1
0
    def test_compile_template(self):
        """Test that functions with templates are correctly expanded and compiled."""

        # Push commuting gates to the right and merging rotations gives a circuit
        # with alternating RX and CNOT gates
        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))

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

        pipeline = [commute_controlled, merge_rotations]
        transformed_qfunc = compile(pipeline=pipeline)(qfunc)
        transformed_qnode = qml.QNode(transformed_qfunc, dev)

        x = np.array([0.1, 0.2, 0.3])
        params = np.ones((2, 3))

        original_result = qnode(x, params)
        transformed_result = transformed_qnode(x, params)
        assert np.allclose(original_result, transformed_result)

        names_expected = ["RX", "CNOT"] * 6
        wires_expected = [
            Wires(0),
            Wires([0, 1]),
            Wires(1),
            Wires([1, 2]),
            Wires(2),
            Wires([2, 0]),
        ] * 2

        compare_operation_lists(transformed_qnode.qtape.operations, names_expected, wires_expected)
Exemplo n.º 2
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)
Exemplo n.º 3
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)
Exemplo n.º 4
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)
Exemplo n.º 5
0
    def test_compile_default_pipeline(self, wires):
        """Test that the default pipeline returns the correct results."""

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

        qnode = qml.QNode(qfunc, dev)

        transformed_qfunc = compile()(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", "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)
Exemplo n.º 6
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)
Exemplo n.º 7
0
    def test_compile_invalid_num_passes(self):
        """Test that error is raised for an invalid number of passes."""
        qfunc = build_qfunc([0, 1, 2])
        dev = qml.device("default.qubit", wires=[0, 1, 2])

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

        with pytest.raises(ValueError, match="Number of passes must be an integer"):
            transformed_qnode(0.1, 0.2, 0.3)
Exemplo n.º 8
0
    def test_compile_invalid_pipeline(self):
        """Test that error is raised for an invalid function in the pipeline"""
        qfunc = build_qfunc([0, 1, 2])
        dev = qml.device("default.qubit", wires=[0, 1, 2])

        transformed_qfunc = compile(pipeline=[cancel_inverses, isinstance])(qfunc)
        transformed_qnode = qml.QNode(transformed_qfunc, dev)

        with pytest.raises(ValueError, match="Invalid transform function"):
            transformed_qnode(0.1, 0.2, 0.3)
Exemplo n.º 9
0
            def run_pipeline(self):
                pipeline = [
                    qml.transforms.single_tape_transform(DummyTransforms.merge_rotations),
                    qml.transforms.single_tape_transform(DummyTransforms.commute_controlled),
                ]

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

                transformed_qfunc = compile(pipeline=pipeline, num_passes=num_passes)(qfunc)
                transformed_qnode = qml.QNode(transformed_qfunc, dev)
                transformed_result = transformed_qnode(0.3, 0.4, 0.5)
Exemplo n.º 10
0
    def test_compile_empty_pipeline(self, wires):
        """Test that an empty pipeline returns the original function."""

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

        qnode = qml.QNode(qfunc, dev)

        transformed_qfunc = compile(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 = [op.name for op in qnode.qtape.operations]
        wires_expected = [op.wires for op in qnode.qtape.operations]

        compare_operation_lists(transformed_qnode.qtape.operations, names_expected, wires_expected)
Exemplo n.º 11
0
            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]),
    Wires(1),
    Wires(2),