Repository: PennyLaneAI/pennylane
Pull request #7500 (2025-05-27 17:36:57)

Raise `UserWarning` for `set_shots` confusing usage
**Context:**
This PR implements the first `PennyLaneUserWarning` as to indicate the specific setting order when two sources of `shots` setup come up together after `set_shots` is alive:
```python
@qml.qnode(qml.device('default.qubit'))
def c():
    return qml.sample(wires=0)

qml.set_shots(c, 10)(shots=20)  # A PLUW to come up
```

**Description of the Change:**
Make sure there's a `PLUW` raised when then mentioned usage was executed at system level.

**Benefits:**

**Possible Drawbacks:**

**Related GitHub Issues:**
[sc-92096]

github-actions[bot]: Hello. You may have forgotten to update the changelog!
Please edit [`doc/releases/changelog-dev.md`](/PennyLaneAI/pennylane/blob/master/doc/releases/changelog-dev.md) with:
* A one-to-two sentence description of the change. You may include a small working example for new features.
* A link back to this PR.
* Your name (or GitHub username) in the contributors section.
JerryChen97: Should revert whatever introduced by PLUW soon
andrijapau: What about this scenario? 

<img width="559" alt="image" src="https://github.com/user-attachments/assets/5b8a2f52-46c1-484d-9953-1ad371b2c1e9" />

JerryChen97: > What about this scenario?
> <img alt="image" width="559" src="https://private-user-images.githubusercontent.com/46359773/448595929-5b8a2f52-46c1-484d-9953-1ad371b2c1e9.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NDg0Njg1MTAsIm5iZiI6MTc0ODQ2ODIxMCwicGF0aCI6Ii80NjM1OTc3My80NDg1OTU5MjktNWI4YTJmNTItNDZjMS00ODRkLTk5NTMtMWFkMzcxYjJjMWU5LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTA1MjglMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwNTI4VDIxMzY1MFomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTA3YWI5N2RiMzNkNmY5MTg5ODhmZWFjZTMwODBhZjk0YWZmYWNiYTQ1NjQ3M2MzYmRiOGRlZmU1NWQ3NjU0NjUmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.D5dM9o6Rbuqk5_ZC8YeiZljwqrbyimKiOe9W5MXq7GE">

To be deprecated next release! But we secretly allow them for now.
JerryChen97: More precisely, `device(..., shots=...)` will be deprecated.
albi3ro: > What about this scenario?
> 
> <img alt="image" width="559" src="https://private-user-images.githubusercontent.com/46359773/448595929-5b8a2f52-46c1-484d-9953-1ad371b2c1e9.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NDg0Njg1NDQsIm5iZiI6MTc0ODQ2ODI0NCwicGF0aCI6Ii80NjM1OTc3My80NDg1OTU5MjktNWI4YTJmNTItNDZjMS00ODRkLTk5NTMtMWFkMzcxYjJjMWU5LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTA1MjglMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwNTI4VDIxMzcyNFomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWZiNjExMzZmNmE3ODdmZjkyOWVmYjk3NzhlNmNkZTNmNjhiYWQ3MGE5NzhmOWJmZjVkNTBiMWZkYWYzODA1NjMmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.sjzx50KjKKCmtjGcz38tKmKxf81RPKUjZlGmAwOvIQ4">

So `circuit(shots=new_shots)` has been a way of "overriding" the number of shots. Now we have two ways of "overriding" and we want to be clear about which takes precendence. Setting them on the device is the "default". For me, these seems separate enough. But if it does start causing confusion, we could act on it.
andrijapau: > > What about this scenario?
> > <img alt="image" width="559" src="https://private-user-images.githubusercontent.com/46359773/448595929-5b8a2f52-46c1-484d-9953-1ad371b2c1e9.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NDg0Njg1NDQsIm5iZiI6MTc0ODQ2ODI0NCwicGF0aCI6Ii80NjM1OTc3My80NDg1OTU5MjktNWI4YTJmNTItNDZjMS00ODRkLTk5NTMtMWFkMzcxYjJjMWU5LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTA1MjglMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwNTI4VDIxMzcyNFomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWZiNjExMzZmNmE3ODdmZjkyOWVmYjk3NzhlNmNkZTNmNjhiYWQ3MGE5NzhmOWJmZjVkNTBiMWZkYWYzODA1NjMmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.sjzx50KjKKCmtjGcz38tKmKxf81RPKUjZlGmAwOvIQ4">
> 
> So `circuit(shots=new_shots)` has been a way of "overriding" the number of shots. Now we have two ways of "overriding" and we want to be clear about which takes precendence. Setting them on the device is the "default". For me, these seems separate enough. But if it does start causing confusion, we could act on it.

Thanks! Yeah, I was just trying to think of an edge case 👍🏼 

Patch:
diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md
index 032ccd8a1..bcfa3d367 100644
--- a/doc/releases/changelog-dev.md
+++ b/doc/releases/changelog-dev.md
@@ -7,6 +7,7 @@
 * A new QNode transform called :func:`~.transforms.set_shots` has been added to set or update the number of shots to be performed, overriding shots specified in the device.
   [(#7337)](https://github.com/PennyLaneAI/pennylane/pull/7337)
   [(#7358)](https://github.com/PennyLaneAI/pennylane/pull/7358)
+  [(#7500)](https://github.com/PennyLaneAI/pennylane/pull/7500)
 
   The :func:`~.transforms.set_shots` transform can be used as a decorator:
 
diff --git a/pennylane/workflow/qnode.py b/pennylane/workflow/qnode.py
index 6d94da508..7563bb9dc 100644
--- a/pennylane/workflow/qnode.py
+++ b/pennylane/workflow/qnode.py
@@ -897,6 +897,13 @@ class QNode:
         return _to_qfunc_output_type(res, self._qfunc_output, tape.shots.has_partitioned_shots)
 
     def __call__(self, *args, **kwargs) -> qml.typing.Result:
+        if "shots" in kwargs and qml.set_shots in self.transform_program:
+            warnings.warn(
+                "Both 'shots=' parameter and 'set_shots' transform are specified. "
+                "The transform will take precedence over 'shots='",
+                UserWarning,
+                stacklevel=2,
+            )
         if qml.capture.enabled():
             from ._capture_qnode import capture_qnode  # pylint: disable=import-outside-toplevel
 


Test patch:
diff --git a/tests/pytest.ini b/tests/pytest.ini
index 9a08bfc53..c9b06342e 100644
--- a/tests/pytest.ini
+++ b/tests/pytest.ini
@@ -29,6 +29,7 @@ filterwarnings =
     error::pennylane.exceptions.PennyLaneDeprecationWarning
     # Suppress expected AutoGraphWarnings that arise from the tests
     error:AutoGraph will not transform the function:pennylane.capture.autograph.AutoGraphWarning
+    error:Both 'shots=' parameter and 'set_shots' transform are specified. :UserWarning
 #addopts = --benchmark-disable
 xfail_strict=true
 rng_salt = v0.41.0
diff --git a/tests/transforms/test_set_shots.py b/tests/transforms/test_set_shots.py
index 058b297fa..94cdcd9a8 100644
--- a/tests/transforms/test_set_shots.py
+++ b/tests/transforms/test_set_shots.py
@@ -195,3 +195,20 @@ class TestSetShots:
 
         # Parameter-shift rule requires 2*num_params + 1 = 3 executions
         assert len(tracker_shots.history["executions"]) == 3
+
+    @pytest.mark.system
+    def test_ambiguous_shots_configuration_warning(self):
+        """
+        Test that using set_shots with a QNode that has a shots value
+        raises a UserWarning.
+        """
+
+        @qml.qnode(qml.device("default.qubit"))
+        def c():
+            return qml.sample(wires=0)
+
+        with pytest.warns(
+            UserWarning,
+            match=r"The transform will take precedence",
+        ):
+            set_shots(c, shots=10)(shots=20)