コード例 #1
0
ファイル: test_compile.py プロジェクト: thisac/pennylane
    def test_compile_jax(self, diff_method):
        """Test QNode and gradient in JAX interface."""
        jax = pytest.importorskip("jax")
        from jax import numpy as jnp

        from jax.config import config

        remember = config.read("jax_enable_x64")
        config.update("jax_enable_x64", True)

        original_qnode = qml.QNode(qfunc, dev, interface="jax", diff_method=diff_method)
        transformed_qnode = qml.QNode(
            transformed_qfunc, dev, interface="jax", diff_method=diff_method
        )

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

        # Check that the numerical output is the same
        assert qml.math.allclose(original_qnode(x, params), transformed_qnode(x, params))

        # Check that the gradient is the same
        assert qml.math.allclose(
            jax.grad(original_qnode, argnums=(1))(x, params),
            jax.grad(transformed_qnode, argnums=(1))(x, params),
            atol=1e-7,
        )

        # Check operation list
        ops = transformed_qnode.qtape.operations
        compare_operation_lists(ops, expected_op_list, expected_wires_list)
コード例 #2
0
ファイル: test_compile.py プロジェクト: thisac/pennylane
    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)
コード例 #3
0
ファイル: test_compile.py プロジェクト: thisac/pennylane
    def test_compile_torch(self):
        """Test QNode and gradient in torch interface."""
        torch = pytest.importorskip("torch", minversion="1.8")

        original_qnode = qml.QNode(qfunc, dev, interface="torch", diff_method="parameter-shift")
        transformed_qnode = qml.QNode(
            transformed_qfunc, dev, interface="torch", diff_method="parameter-shift"
        )

        original_x = torch.tensor([0.3, -0.2, 0.8], requires_grad=False)
        original_params = torch.ones((2, 3), requires_grad=True)

        transformed_x = torch.tensor([0.3, -0.2, 0.8], requires_grad=False)
        transformed_params = torch.ones((2, 3), requires_grad=True)

        original_result = original_qnode(original_x, original_params)
        transformed_result = transformed_qnode(transformed_x, transformed_params)

        # Check that the numerical output is the same
        assert qml.math.allclose(original_result, transformed_result)

        # Check that the gradient is the same
        original_result.backward()
        transformed_result.backward()

        assert qml.math.allclose(original_params.grad, transformed_params.grad)

        # Check operation list
        ops = transformed_qnode.qtape.operations
        compare_operation_lists(ops, expected_op_list, expected_wires_list)
コード例 #4
0
ファイル: test_compile.py プロジェクト: thisac/pennylane
    def test_compile_tf(self, diff_method):
        """Test QNode and gradient in tensorflow interface."""
        tf = pytest.importorskip("tensorflow")

        original_qnode = qml.QNode(qfunc, dev, interface="tf", diff_method=diff_method)
        transformed_qnode = qml.QNode(
            transformed_qfunc, dev, interface="tf", diff_method=diff_method
        )

        original_x = tf.Variable([0.8, -0.6, 0.4])
        original_params = tf.Variable(tf.ones((2, 3)))

        transformed_x = tf.Variable([0.8, -0.6, 0.4])
        transformed_params = tf.Variable(tf.ones((2, 3)))

        original_result = original_qnode(original_x, original_params)
        transformed_result = transformed_qnode(transformed_x, transformed_params)

        # Check that the numerical output is the same
        assert qml.math.allclose(original_result, transformed_result)

        # Check that the gradient is the same
        with tf.GradientTape() as tape:
            loss = original_qnode(original_x, original_params)
        original_grad = tape.gradient(loss, original_params)

        with tf.GradientTape() as tape:
            loss = transformed_qnode(transformed_x, transformed_params)
        transformed_grad = tape.gradient(loss, transformed_params)

        assert qml.math.allclose(original_grad, transformed_grad)

        # Check operation list
        ops = transformed_qnode.qtape.operations
        compare_operation_lists(ops, expected_op_list, expected_wires_list)
コード例 #5
0
ファイル: test_compile.py プロジェクト: thisac/pennylane
    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)
コード例 #6
0
ファイル: test_compile.py プロジェクト: thisac/pennylane
    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)
コード例 #7
0
ファイル: test_compile.py プロジェクト: thisac/pennylane
    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
ファイル: test_compile.py プロジェクト: thisac/pennylane
    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)
コード例 #9
0
    def test_compile_autograd(self, diff_method):
        """Test QNode and gradient in autograd interface."""

        original_qnode = qml.QNode(qfunc,
                                   dev,
                                   interface="autograd",
                                   diff_method=diff_method)
        transformed_qnode = qml.QNode(transformed_qfunc,
                                      dev,
                                      interface="autograd",
                                      diff_method=diff_method)

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

        # Check that the numerical output is the same
        assert qml.math.allclose(original_qnode(x, params),
                                 transformed_qnode(x, params))

        # Check that the gradient is the same
        assert qml.math.allclose(
            qml.grad(original_qnode)(x, params),
            qml.grad(transformed_qnode)(x, params))

        # Check operation list
        ops = transformed_qnode.qtape.operations
        compare_operation_lists(ops, expected_op_list, expected_wires_list)
コード例 #10
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)
コード例 #11
0
ファイル: test_compile.py プロジェクト: thisac/pennylane
    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)