Repository: PennyLaneAI/pennylane
Pull request #2114 (2022-01-19 16:32:19)

Raise error upon request of backpropagation on device with finite shots
Fixes Issue #1481 on the new QNode, as previous fix #1588 only solved the problem on the old QNode.

Contrary to the last bugfix on this problem, this fix raises an error instead of a warning.

```
dev = qml.device('default.qubit.autograd', shots=10, wires=1)

@qml.qnode(dev, interface='autograd', diff_method='backprop')
def circ(x):
    qml.RX(x, wires=0)
    return qml.expval(qml.PauliZ(0))
```
Now raises a `QuantumFunctionError`.


[sc-8003]


Patch:
diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md
index c497522d1..157818680 100644
--- a/doc/releases/changelog-dev.md
+++ b/doc/releases/changelog-dev.md
@@ -426,6 +426,10 @@
 
 <h3>Bug fixes</h3>
 
+* An error is raised during QNode creation if backpropagation is requested on a device with
+  finite-shots specified.
+  [(#2114)](https://github.com/PennyLaneAI/pennylane/pull/2114)
+
 * Pytest now ignores any `DeprecationWarning` raised within autograd's `numpy_wrapper` module.
   Other assorted minor test warnings are fixed.
   [(#2007)](https://github.com/PennyLaneAI/pennylane/pull/2007)
diff --git a/pennylane/qnode.py b/pennylane/qnode.py
index ab9f54300..1e17da4fa 100644
--- a/pennylane/qnode.py
+++ b/pennylane/qnode.py
@@ -372,6 +372,9 @@ class QNode:
                 "Device caching is incompatible with the backprop diff_method"
             )
 
+        if device.shots is not None:
+            raise qml.QuantumFunctionError("Backpropagation is only supported when shots=None.")
+
         if backprop_interface is not None:
             # device supports backpropagation natively
 
@@ -384,30 +387,27 @@ class QNode:
             )
 
         if backprop_devices is not None:
-            if device.shots is None:
-                # device is analytic and has child devices that support backpropagation natively
-
-                if interface in backprop_devices:
-                    # TODO: need a better way of passing existing device init options
-                    # to a new device?
-                    expand_fn = device.expand_fn
-                    batch_transform = device.batch_transform
-
-                    device = qml.device(
-                        backprop_devices[interface],
-                        wires=device.wires,
-                        shots=device.shots,
-                    )
-                    device.expand_fn = expand_fn
-                    device.batch_transform = batch_transform
-                    return "backprop", {}, device
-
-                raise qml.QuantumFunctionError(
-                    f"Device {device.short_name} only supports diff_method='backprop' when using the "
-                    f"{list(backprop_devices.keys())} interfaces."
+            # device is analytic and has child devices that support backpropagation natively
+
+            if interface in backprop_devices:
+                # TODO: need a better way of passing existing device init options
+                # to a new device?
+                expand_fn = device.expand_fn
+                batch_transform = device.batch_transform
+
+                device = qml.device(
+                    backprop_devices[interface],
+                    wires=device.wires,
+                    shots=device.shots,
                 )
+                device.expand_fn = expand_fn
+                device.batch_transform = batch_transform
+                return "backprop", {}, device
 
-            raise qml.QuantumFunctionError("Backpropagation is only supported when shots=None.")
+            raise qml.QuantumFunctionError(
+                f"Device {device.short_name} only supports diff_method='backprop' when using the "
+                f"{list(backprop_devices.keys())} interfaces."
+            )
 
         raise qml.QuantumFunctionError(
             f"The {device.short_name} device does not support native computations with "


Test patch:
diff --git a/tests/devices/test_default_qubit_jax.py b/tests/devices/test_default_qubit_jax.py
index 48c308d3e..165f59744 100644
--- a/tests/devices/test_default_qubit_jax.py
+++ b/tests/devices/test_default_qubit_jax.py
@@ -170,10 +170,10 @@ class TestQNodeIntegration:
         dev = qml.device("default.qubit.jax", wires=1, shots=100)
         expected = jnp.array([0.0, 1.0])
 
-        @qml.qnode(dev, interface="jax")
+        @qml.qnode(dev, interface="jax", diff_method=None)
         def circuit():
             qml.PauliX(wires=0)
-            return qml.probs()
+            return qml.probs(wires=0)
 
         result = circuit()
         assert jnp.allclose(result, expected, atol=tol)
@@ -184,10 +184,10 @@ class TestQNodeIntegration:
         expected = jnp.array([0.0, 1.0])
 
         @jax.jit
-        @qml.qnode(dev, interface="jax")
+        @qml.qnode(dev, interface="jax", diff_method=None)
         def circuit():
             qml.PauliX(wires=0)
-            return qml.probs()
+            return qml.probs(wires=0)
 
         result = circuit()
         assert jnp.allclose(result, expected, atol=tol)
@@ -198,10 +198,10 @@ class TestQNodeIntegration:
         expected = jnp.array([[0.0, 1.0], [0.0, 1.0]])
 
         @jax.jit
-        @qml.qnode(dev, interface="jax")
+        @qml.qnode(dev, diff_method=None, interface="jax")
         def circuit():
             qml.PauliX(wires=0)
-            return qml.probs()
+            return qml.probs(wires=0)
 
         result = circuit()
         assert jnp.allclose(result, expected, atol=tol)
diff --git a/tests/test_qnode.py b/tests/test_qnode.py
index 6329d5461..60237372d 100644
--- a/tests/test_qnode.py
+++ b/tests/test_qnode.py
@@ -157,6 +157,14 @@ class TestValidation:
         ):
             QNode._validate_backprop_method(dev, "another_interface")
 
+    @pytest.mark.parametrize("device_string", ("default.qubit", "default.qubit.autograd"))
+    def test_validate_backprop_finite_shots(self, device_string):
+        """Test that a device with finite shots cannot be used with backpropagation."""
+        dev = qml.device(device_string, wires=1, shots=100)
+
+        with pytest.raises(qml.QuantumFunctionError, match=r"Backpropagation is only supported"):
+            QNode._validate_backprop_method(dev, "autograd")
+
     def test_parameter_shift_qubit_device(self):
         """Test that the _validate_parameter_shift method
         returns the correct gradient transform for qubit devices."""