Beispiel #1
0
    def test_merge_rotations_autograd(self):
        """Test QNode and gradient in autograd interface."""

        original_qnode = qml.QNode(qfunc, dev)
        transformed_qnode = qml.QNode(transformed_qfunc, dev)

        input = np.array([0.1, 0.2, 0.3, 0.4], requires_grad=True)

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

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

        # Check operation list
        ops = transformed_qnode.qtape.operations
        compare_operation_lists(ops, expected_op_list, expected_wires_list)
    def test_controlled_rotation_second_derivative(self, G, tol):
        """Test that the controlled rotation gates return the correct
        second derivative if first decomposed."""
        dev = qml.device("default.qubit", wires=2)
        init_state = qml.numpy.array([1.0, -1.0], requires_grad=False) / np.sqrt(2)

        @qml.qnode(dev)
        def circuit(b):
            qml.QubitStateVector(init_state, wires=0)
            G(b, wires=[0, 1])
            return qml.expval(qml.PauliX(0))

        b = 0.123

        res = circuit(b)
        assert np.allclose(res, -np.cos(b / 2), atol=tol, rtol=0)

        grad = qml.grad(qml.grad(circuit))(b)
        expected = np.cos(b / 2) / 4
        assert np.allclose(grad, expected, atol=tol, rtol=0)
    def test_non_differentiable_gradient(self):
        """Test gradient computation with requires_grad=False raises an error"""

        def cost(x):
            return np.sum(np.sin(x))

        grad_fn = qml.grad(cost, argnum=[0])
        arr1 = np.array([0.0, 1.0, 2.0], requires_grad=False)

        with pytest.raises(np.NonDifferentiableError, match="non-differentiable"):
            grad_fn(arr1)
Beispiel #4
0
    def test_tracker(self):
        """Tests the device tracker with batch execution."""
        dev = qml.device('qiskit.aer', shots=100, wires=3)

        @qml.qnode(dev, diff_method="parameter-shift")
        def circuit(x):
            qml.RX(x, wires=0)
            return qml.expval(qml.PauliZ(0))

        x = tensor(0.1, requires_grad=True)

        with qml.Tracker(dev) as tracker:
            qml.grad(circuit)(x)

        expected = {'executions': [1, 1, 1],
                     'shots': [100, 100, 100],
                     'batches': [1, 1],
                     'batch_len': [1, 2]}

        assert tracker.history == expected
    def test_non_scalar_cost_gradient(self):
        """Test gradient computation with a non-scalar cost function raises an error"""

        def cost(x):
            return np.sin(x)

        grad_fn = qml.grad(cost, argnum=[0])
        arr1 = np.array([0.0, 1.0, 2.0], requires_grad=True)

        with pytest.raises(TypeError, match="only applies to real scalar-output functions"):
            grad_fn(arr1)
def test_integration():
    """Test that the execution of lightning.qubit is possible and agrees with default.qubit"""
    wires = 2
    layers = 2
    dev_l = qml.device("lightning.qubit", wires=wires)
    dev_d = qml.device("default.qubit", wires=wires)

    def circuit(weights):
        qml.templates.StronglyEntanglingLayers(weights, wires=range(wires))
        return qml.expval(qml.PauliZ(0))

    np.random.seed(1967)
    weights = np.random.random(
        qml.templates.StronglyEntanglingLayers.shape(layers, wires))

    qn_l = qml.QNode(circuit, dev_l)
    qn_d = qml.QNode(circuit, dev_d)

    assert np.allclose(qn_l(weights), qn_d(weights))
    assert np.allclose(qml.grad(qn_l)(weights), qml.grad(qn_d)(weights))
Beispiel #7
0
    def test_gradient_autograd(self, mocker):
        """Test that caching works when calculating the gradient method using the autograd
        interface"""
        qnode = get_qnode(caching=10, interface="autograd")
        d_qnode = qml.grad(qnode)
        args = [0.1, 0.2]

        d_qnode(*args)
        spy = mocker.spy(DefaultQubitAutograd, "execute")
        d_qnode(*args)
        spy.assert_not_called()
Beispiel #8
0
    def test_sin(self, tol):
        """Tests gradients with multivariate sin and cosine."""
        multi_var = lambda x: np.sin(x[0]) + np.cos(x[1])
        grad_multi_var = lambda x: np.array([np.cos(x[0]), -np.sin(x[1])])

        x_vec = [1.5, -2.5]
        g = qml.grad(multi_var, 0)
        auto_grad = g(x_vec)
        correct_grad = grad_multi_var(x_vec)

        assert np.allclose(auto_grad, correct_grad, atol=tol, rtol=0)
    def test_hamiltonian_dif_autograd(self):
        """Tests that the hamiltonian_expand tape transform is differentiable with the Autograd interface"""

        H = qml.Hamiltonian(
            [-0.2, 0.5, 1], [qml.PauliX(1), qml.PauliZ(1) @ qml.PauliY(2), qml.PauliZ(0)]
        )

        var = [
            np.array(0.1),
            np.array(0.67),
            np.array(0.3),
            np.array(0.4),
            np.array(-0.5),
            np.array(0.7),
            np.array(0.4),
            np.array(-0.5),
            np.array(0.7),
        ]
        output = 0.42294409781940356
        output2 = [
            9.68883500e-02,
            -2.90832724e-01,
            -1.04448033e-01,
            -1.94289029e-09,
            3.50307411e-01,
            -3.41123470e-01,
            0.0,  # these three are the Hamiltonian parameters
            0.0,
            0.0,
        ]

        with qml.tape.JacobianTape() as tape:
            for i in range(2):
                qml.RX(np.array(0), wires=0)
                qml.RX(np.array(0), wires=1)
                qml.RX(np.array(0), wires=2)
                qml.CNOT(wires=[0, 1])
                qml.CNOT(wires=[1, 2])
                qml.CNOT(wires=[2, 0])

            qml.expval(H)

        AutogradInterface.apply(tape)

        def cost(x):
            tape.set_parameters(x, trainable_only=False)
            tapes, fn = qml.transforms.hamiltonian_expand(tape)
            res = [t.execute(dev) for t in tapes]
            return fn(res)

        assert np.isclose(cost(var), output)
        grad = qml.grad(cost)(var)
        for g, o in zip(grad, output2):
            assert np.allclose(g, o)
Beispiel #10
0
    def test_agrees_with_autograd(self, tol):
        """Test that the grad function agrees with autograd"""
        def cost(x):
            return np.sum(np.sin(x) * x[0]**3)

        grad_fn = qml.grad(cost)
        params = np.array([0.5, 1.0, 2.0], requires_grad=True)
        res = grad_fn(params)
        expected = autograd.grad(cost)(params)

        assert np.allclose(res, expected, atol=tol, rtol=0)
Beispiel #11
0
def test_autodifferentiation():
    """Test that autodifferentiation is preserved when writing
    a cost function that uses TensorBox method chaining"""
    x = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])

    cost_fn = lambda a: (qml.proc.TensorBox(a).T**2).unbox()[0, 1]
    grad_fn = qml.grad(cost_fn)

    res = grad_fn(x)[0]
    expected = np.array([[0.0, 0.0, 0.0], [8.0, 0.0, 0.0]])
    assert np.all(res == expected)
    def test_hermitian_expectation(self, device, tol):
        """Test that arbitrary multi-mode Hermitian expectation values are correct"""
        n_wires = 2
        dev = device(n_wires)
        dev_def = qml.device("default.qubit", wires=n_wires)

        if dev.shots is not None:
            pytest.skip("Device is in non-analytical mode.")

        if "Hermitian" not in dev.observables:
            pytest.skip("Device does not support the Hermitian observable.")

        if dev.name == dev_def.name:
            pytest.skip("Device is default.qubit.")

        theta = 0.432
        phi = 0.123
        A_ = np.array(
            [
                [-6, 2 + 1j, -3, -5 + 2j],
                [2 - 1j, 0, 2 - 1j, -5 + 4j],
                [-3, 2 + 1j, 0, -4 + 3j],
                [-5 - 2j, -5 - 4j, -4 - 3j, -6],
            ]
        )
        A_.requires_grad = False

        def circuit(theta, phi):
            qml.RX(theta, wires=[0])
            qml.RX(phi, wires=[1])
            qml.CNOT(wires=[0, 1])
            return qml.expval(qml.Hermitian(A_, wires=[0, 1]))

        qnode_def = qml.QNode(circuit, dev_def)
        qnode = qml.QNode(circuit, dev)

        grad_def = qml.grad(qnode_def, argnum=[0, 1])
        grad = qml.grad(qnode, argnum=[0, 1])

        assert np.allclose(qnode(theta, phi), qnode_def(theta, phi), atol=tol(dev.shots))
        assert np.allclose(grad(theta, phi), grad_def(theta, phi), atol=tol(dev.shots))
Beispiel #13
0
    def test_parameter_shift_hessian(self, params, tol):
        """Tests that the output of the parameter-shift transform
        can be differentiated using autograd, yielding second derivatives."""
        dev = qml.device("default.qubit.autograd", wires=2)
        params = np.array([0.543, -0.654], requires_grad=True)

        def cost_fn(x):
            with qml.tape.JacobianTape() as tape1:
                qml.RX(x[0], wires=[0])
                qml.RY(x[1], wires=[1])
                qml.CNOT(wires=[0, 1])
                qml.var(qml.PauliZ(0) @ qml.PauliX(1))

            with qml.tape.JacobianTape() as tape2:
                qml.RX(x[0], wires=0)
                qml.RY(x[0], wires=1)
                qml.CNOT(wires=[0, 1])
                qml.probs(wires=1)

            result = execute([tape1, tape2], dev, gradient_fn=param_shift)
            return result[0] + result[1][0, 0]

        res = cost_fn(params)
        x, y = params
        expected = 0.5 * (3 + np.cos(x)**2 * np.cos(2 * y))
        assert np.allclose(res, expected, atol=tol, rtol=0)

        res = qml.grad(cost_fn)(params)
        expected = np.array([
            -np.cos(x) * np.cos(2 * y) * np.sin(x),
            -np.cos(x)**2 * np.sin(2 * y)
        ])
        assert np.allclose(res, expected, atol=tol, rtol=0)

        res = qml.jacobian(qml.grad(cost_fn))(params)
        expected = np.array([
            [-np.cos(2 * x) * np.cos(2 * y),
             np.sin(2 * x) * np.sin(2 * y)],
            [np.sin(2 * x) * np.sin(2 * y), -2 * np.cos(x)**2 * np.cos(2 * y)],
        ])
        assert np.allclose(res, expected, atol=tol, rtol=0)
Beispiel #14
0
    def test_differentiable_autograd(self, diff_method):
        """Test that a batch transform is differentiable when using
        autograd"""
        dev = qml.device("default.qubit", wires=2)
        qnode = qml.QNode(self.circuit,
                          dev,
                          interface="autograd",
                          diff_method=diff_method)

        def cost(x, weights):
            return self.my_transform(qnode, weights)(x)

        weights = np.array([0.1, 0.2], requires_grad=True)
        x = np.array(0.543, requires_grad=True)

        res = cost(x, weights)
        assert np.allclose(res, self.expval(x, weights))

        grad = qml.grad(cost)(x, weights)
        expected = qml.grad(self.expval)(x, weights)
        assert all(np.allclose(g, e) for g, e in zip(grad, expected))
Beispiel #15
0
    def test_integration_qubit_grad(self, template, diffable, nondiffable,
                                    n_wires, interface, to_var):
        """Tests that gradient calculations of qubit templates execute without error."""
        if template.__name__ in ["AmplitudeEmbedding"]:
            pytest.skip("Template cannot be differentiated")

        # Extract keys and items
        keys_diffable = [*diffable]
        diffable = list(diffable.values())

        # Turn into correct format
        diffable = [to_var(i) for i in diffable]

        # Make qnode
        dev = qml.device('default.qubit', wires=n_wires)

        @qml.qnode(dev, interface=interface)
        def circuit(*diffable):

            # Turn diffables back into dictionaries
            dict = {key: item for key, item in zip(keys_diffable, diffable)}

            # Merge diffables and nondiffables
            dict.update(nondiffable)

            # Circuit
            template(**dict)
            return qml.expval(qml.Identity(0))

        # Do gradient check for every differentiable argument
        for argnum in range(len(diffable)):

            # Check gradients in numpy interface
            if interface == 'autograd':
                grd = qml.grad(circuit, argnum=[argnum])
                grd(*diffable)

            # Check gradients in torch interface
            if interface == 'torch':
                for i in range(len(diffable)):
                    if i != argnum:
                        diffable[i].requires_grad = False
                diffable[argnum].requires_grad = True

                res = circuit(*diffable)
                res.backward()
                diffable[argnum].grad.numpy()

            # Check gradients in tf interface
            if interface == 'tf':
                with tf.GradientTape() as tape:
                    loss = circuit(*diffable)
                    tape.gradient(loss, diffable[argnum])
Beispiel #16
0
    def test_no_trainable_params_deprecation_grad(self, recwarn):
        """Tests that no deprecation warning arises when using qml.grad with
        qml.math.is_independent.
        """
        def lin(x):
            return pnp.sum(x)

        x = pnp.array([0.2, 9.1, -3.2], requires_grad=True)
        jac = qml.grad(lin)
        assert qml.math.is_independent(jac, "autograd", (x, ), {})

        assert len(recwarn) == 0
Beispiel #17
0
    def test_decomposition_integration(self, angle, tol):
        """Test that the decompositon of PauliRot yields the same results."""

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

        @qml.qnode(dev)
        def circuit(theta):
            qml.PauliRot(theta, "XX", wires=[0, 1])

            return qml.expval(qml.PauliZ(0))

        @qml.qnode(dev)
        def decomp_circuit(theta):
            qml.PauliRot.decomposition(theta, "XX", wires=[0, 1])

            return qml.expval(qml.PauliZ(0))

        assert circuit(angle) == pytest.approx(decomp_circuit(angle), abs=tol)
        assert np.squeeze(qml.grad(circuit)(angle)) == pytest.approx(
            np.squeeze(qml.grad(decomp_circuit)(angle)), abs=tol
        )
Beispiel #18
0
def test__tape_qchem(tol):
    """The circit Ansatz with a QChem Hamiltonian produces correct results"""

    H, qubits = qml.qchem.molecular_hamiltonian(
        ["H", "H"], np.array([0.0, 0.1, 0.0, 0.0, -0.1, 0.0]))

    def circuit(params):
        circuit_ansatz(params, wires=range(4))
        return qml.expval(H)

    params = np.arange(30) * 0.111

    dev_lq = qml.device("lightning.qubit", wires=4)
    dev_dq = qml.device("default.qubit", wires=4)

    circuit_lq = qml.QNode(circuit, dev_lq, diff_method="adjoint")
    circuit_dq = qml.QNode(circuit, dev_lq, diff_method="parameter-shift")

    assert np.allclose(
        qml.grad(circuit_lq)(params),
        qml.grad(circuit_dq)(params), tol)
Beispiel #19
0
    def test_linear(self, tol):
        """Tests gradients with multivariate multidimensional linear func."""
        x_vec = np.random.uniform(-5, 5, size=(2))
        x_vec_multidim = np.expand_dims(x_vec, axis=1)

        gradf = lambda x: np.array([[2 * x_[0]] for x_ in x])
        f = lambda x: np.sum([x_[0]**2 for x_ in x])

        g = qml.grad(f, 0)
        auto_grad = g(x_vec_multidim)
        correct_grad = gradf(x_vec_multidim)
        assert np.allclose(auto_grad, correct_grad, atol=tol, rtol=0)
Beispiel #20
0
    def test_gradient_autograd(self, mocker):
        """Test that caching works when calculating the gradient using the autograd
        interface"""
        dev = qml.device("default.qubit", wires=2, cache=10)
        qn = QNode(qfunc, dev, interface="autograd")
        d_qnode = qml.grad(qn)
        args = [0.1, 0.2]

        d_qnode(*args)
        spy = mocker.spy(DefaultQubit, "apply")
        d_qnode(*args)
        spy.assert_not_called()
Beispiel #21
0
    def test_hessian_vector_valued_postprocessing(self, dev_name, diff_method, mocker, tol):
        """Test hessian calculation of a vector valued QNode with post-processing"""
        if diff_method not in {"parameter-shift", "backprop"}:
            pytest.skip("Test only supports parameter-shift or backprop")

        dev = qml.device(dev_name, wires=1)

        @qnode(dev, diff_method=diff_method, interface="autograd")
        def circuit(x):
            qml.RX(x[0], wires=0)
            qml.RY(x[1], wires=0)
            return [qml.expval(qml.PauliZ(0)), qml.expval(qml.PauliZ(0))]

        def cost_fn(x):
            return x @ circuit(x)

        x = np.array([0.76, -0.87], requires_grad=True)
        res = cost_fn(x)

        a, b = x

        expected_res = x @ [np.cos(a) * np.cos(b), np.cos(a) * np.cos(b)]
        assert np.allclose(res, expected_res, atol=tol, rtol=0)

        grad_fn = qml.grad(cost_fn)
        g = grad_fn(x)

        expected_g = [
            np.cos(b) * (np.cos(a) - (a + b) * np.sin(a)),
            np.cos(a) * (np.cos(b) - (a + b) * np.sin(b)),
        ]
        assert np.allclose(g, expected_g, atol=tol, rtol=0)

        spy = mocker.spy(JacobianTape, "hessian")
        hess = qml.jacobian(grad_fn)(x)

        if diff_method == "backprop":
            spy.assert_not_called()
        elif diff_method == "parameter-shift":
            spy.assert_called_once()

        expected_hess = [
            [
                -(np.cos(b) * ((a + b) * np.cos(a) + 2 * np.sin(a))),
                -(np.cos(b) * np.sin(a)) + (-np.cos(a) + (a + b) * np.sin(a)) * np.sin(b),
            ],
            [
                -(np.cos(b) * np.sin(a)) + (-np.cos(a) + (a + b) * np.sin(a)) * np.sin(b),
                -(np.cos(a) * ((a + b) * np.cos(b) + 2 * np.sin(b))),
            ],
        ]

        assert np.allclose(hess, expected_hess, atol=tol, rtol=0)
Beispiel #22
0
    def test_autograd(self, tol):
        """Tests the autograd interface."""

        features = pnp.array([1.0, 1.0, 1.0], requires_grad=True)

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

        circuit = qml.QNode(circuit_template, dev)
        circuit2 = qml.QNode(circuit_decomposed, dev)

        res = circuit(features)
        res2 = circuit2(features)
        assert qml.math.allclose(res, res2, atol=tol, rtol=0)

        grad_fn = qml.grad(circuit)
        grads = grad_fn(features)

        grad_fn2 = qml.grad(circuit2)
        grads2 = grad_fn2(features)

        assert np.allclose(grads[0], grads2[0], atol=tol, rtol=0)
    def test_sin(self, tol):
        """Tests gradients with multivariate multidimensional sin and cos."""
        x_vec = np.random.uniform(-5, 5, size=(2))
        x_vec_multidim = np.expand_dims(x_vec, axis=1)

        gradf = lambda x: np.array([[np.cos(x[0, 0])], [-np.sin(x[[1]])]], dtype=np.float64)
        f = lambda x: np.sin(x[0, 0]) + np.cos(x[1, 0])

        g = qml.grad(f, 0)
        auto_grad = g(x_vec_multidim)
        correct_grad = gradf(x_vec_multidim)
        assert np.allclose(auto_grad, correct_grad, atol=tol, rtol=0)
Beispiel #24
0
    def test_gradient(self):
        """Test gradient computations continue to work"""
        def cost(x):
            return np.sum(np.sin(x))

        grad_fn = qml.grad(cost, argnum=[0])
        arr1 = np.array([0., 1., 2.])

        res = grad_fn(arr1)
        expected = np.cos(arr1)

        assert np.all(res == expected)
Beispiel #25
0
    def test_autograd(self, tol):
        """Tests the autograd interface."""

        weights = pnp.array(np.random.random(size=(2, )), requires_grad=True)

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

        circuit = qml.QNode(circuit_template, dev)
        circuit2 = qml.QNode(circuit_decomposed, dev)

        res = circuit(weights)
        res2 = circuit2(weights)
        assert qml.math.allclose(res, res2, atol=tol, rtol=0)

        grad_fn = qml.grad(circuit)
        grads = grad_fn(weights)

        grad_fn2 = qml.grad(circuit2)
        grads2 = grad_fn2(weights)

        assert np.allclose(grads, grads2, atol=tol, rtol=0)
Beispiel #26
0
    def test_pauliz_expectation_analytic(self, device, tol):
        """Test that the tensor product of PauliZ expectation value is correct"""
        n_wires = 2
        dev = device(n_wires)
        dev_def = qml.device("default.qubit", wires=n_wires)

        if dev.name == dev_def.name:
            pytest.skip("Device is default.qubit.")

        supports_tensor = ("supports_tensor_observables" in dev.capabilities()
                           and
                           dev.capabilities()["supports_tensor_observables"])

        if not supports_tensor:
            pytest.skip("Device does not support tensor observables.")

        if not dev.analytic:
            pytest.skip("Device is in non-analytical mode.")

        theta = 0.432
        phi = 0.123

        def circuit(theta, phi):
            qml.RX(theta, wires=[0])
            qml.RX(phi, wires=[1])
            qml.CNOT(wires=[0, 1])
            return qml.expval(qml.PauliZ(wires=0) @ qml.PauliZ(wires=1))

        qnode_def = qml.QNode(circuit, dev_def)
        qnode = qml.QNode(circuit, dev)

        grad_def = qml.grad(qnode_def, argnum=[0, 1])
        grad = qml.grad(qnode, argnum=[0, 1])

        assert np.allclose(qnode(theta, phi),
                           qnode_def(theta, phi),
                           atol=tol(dev.analytic))
        assert np.allclose(grad(theta, phi),
                           grad_def(theta, phi),
                           atol=tol(dev.analytic))
Beispiel #27
0
    def test_random_circuit(self, device, tol, ret):
        """Test that the expectation value of a random circuit is correct"""
        n_wires = 2
        dev = device(n_wires)
        dev_def = qml.device("default.qubit", wires=n_wires)

        if dev.name == dev_def.name:
            pytest.skip("Device is default.qubit.")

        supports_tensor = ("supports_tensor_observables" in dev.capabilities()
                           and
                           dev.capabilities()["supports_tensor_observables"])

        if not supports_tensor:
            pytest.skip("Device does not support tensor observables.")

        if not dev.analytic:
            pytest.skip("Device is in non-analytical mode.")

        n_layers = np.random.randint(1, 5)
        weights = 2 * np.pi * np.random.rand(n_layers, 1)

        ret_type = getattr(qml, ret)

        def circuit(weights):
            RandomLayers(weights, wires=range(n_wires))
            return ret_type(qml.PauliZ(wires=0) @ qml.PauliX(wires=1))

        qnode_def = qml.QNode(circuit, dev_def)
        qnode = qml.QNode(circuit, dev)

        grad_def = qml.grad(qnode_def, argnum=0)
        grad = qml.grad(qnode, argnum=0)

        assert np.allclose(qnode(weights),
                           qnode_def(weights),
                           atol=tol(dev.analytic))
        assert np.allclose(grad(weights),
                           grad_def(weights),
                           atol=tol(dev.analytic))
Beispiel #28
0
    def test_autograd_conversion(self, qnode, tol):
        """Tests that the to_autograd() function ignores QNodes that already
        have the autograd interface."""
        converted_qnode = to_autograd(qnode)
        assert converted_qnode is qnode

        x = 0.4
        res = converted_qnode(x)
        assert np.allclose(res, np.cos(x), atol=tol, rtol=0)

        grad_fn = qml.grad(converted_qnode)
        res = grad_fn(x)
        assert np.allclose(res, -np.sin(x), atol=tol, rtol=0)
Beispiel #29
0
    def test_grad_zero_hamiltonian(self, tol):
        """Tests the VQE gradient for a "zero" Hamiltonian."""
        dev = qml.device("default.qubit", wires=4)
        H = qml.Hamiltonian([0], [qml.PauliX(0)])
        w = pnp.array(PARAMS, requires_grad=True)

        @qml.qnode(dev, diff_method="parameter-shift")
        def circuit(w):
            qml.templates.StronglyEntanglingLayers(w, wires=range(4))
            return qml.expval(H)

        dc = qml.grad(circuit)(w)
        assert np.allclose(dc, 0, atol=tol)
Beispiel #30
0
    def test_grad_autograd(self, diff_method, tol):
        """Tests the VQE gradient in the autograd interface."""
        dev = qml.device("default.qubit", wires=4)
        H = big_hamiltonian
        w = pnp.array(PARAMS, requires_grad=True)

        @qml.qnode(dev, diff_method=diff_method)
        def circuit(w):
            qml.templates.StronglyEntanglingLayers(w, wires=range(4))
            return qml.expval(H)

        dc = qml.grad(circuit)(w)
        assert np.allclose(dc, big_hamiltonian_grad, atol=tol)