Skip to content

Commit bb628a2

Browse files
JerryChen97andrijapaualbi3ro
authored
Deprecate device(..., shots=...) base (#7979)
**Context:** `device(..., shots=...)` has been a popular user interface almost everywhere, therefore its deprecation should be taking much longer than a usual one. To ease our work, here is the base PR to help set up the basics: define the deprecation message and **suppress** the deprecation as error for this specific deprecation for now. **Description of the Change:** Source code: - Initialization of a `Device` with `shots=` kwarg will raise a `PennyLaneDeprecationWarning` - within PennyLane codebase, shots extraction from devices will be replaced with QNode shots - `quantum_fisher` use `tape.shots` isntead of `device.shots` - `ShotAdaptiveOptimizer` in `optimize/shot_adaptive.py` checks finite-shots status of qnode instead of `check_device` - Updated docstring of `CoutnsMP` and `SampleMP` Tests: - Whoever used `device(..., shots=...)` have been changed with `set_shots` **Benefits:** **Possible Drawbacks:** - We did not update the legacy device interface - Note that `capture` is still using device shots as a hard requirement - Similarly, the python compiler based on xdsl also requires device shots **Related GitHub Issues:** [sc-90927] --------- Co-authored-by: Andrija Paurevic <[email protected]> Co-authored-by: Christina Lee <[email protected]>
1 parent 7b2701a commit bb628a2

File tree

95 files changed

+1521
-1236
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

95 files changed

+1521
-1236
lines changed

doc/development/deprecations.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,21 @@ deprecations are listed below.
99
Pending deprecations
1010
--------------------
1111

12+
* Setting shots on a device through the `shots=` kwarg is deprecated.
13+
Please use the :func:`pennylane.set_shots` transform on the :class:`~.QNode` instead.
14+
15+
.. code-block:: python
16+
17+
dev = qml.device("default.qubit", wires=2)
18+
@qml.set_shots(1000)
19+
@qml.qnode(dev)
20+
def circuit(x):
21+
qml.RX(x, wires=0)
22+
return qml.expval(qml.Z(0))
23+
24+
- Deprecated in v0.43
25+
- Will be removed in a future version
26+
1227
* Maintenance support for the ``tensorflow`` interface has been deprecated and will be dropped in PennyLane v0.44.
1328
Future versions of PennyLane are not guaranteed to work with TensorFlow.
1429
Instead, we recommend using the :doc:`jax </introduction/interfaces/jax>` or :doc:`torch </introduction/interfaces/torch>` interface for

doc/releases/changelog-dev.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,20 @@
364364

365365
<h3>Deprecations 👋</h3>
366366

367+
* Setting shots on a device through the `shots=` kwarg, e.g. `qml.device("default.qubit", wires=2, shots=1000)`, is deprecated. Please use the `set_shots` transform on the `QNode` instead.
368+
369+
```python
370+
dev = qml.device("default.qubit", wires=2)
371+
372+
@qml.set_shots(1000)
373+
@qml.qnode(dev)
374+
def circuit(x):
375+
qml.RX(x, wires=0)
376+
return qml.expval(qml.Z(0))
377+
```
378+
379+
[(#7979)](https://github.com/PennyLaneAI/pennylane/pull/7979)
380+
367381
* Support for using TensorFlow with PennyLane has been deprecated and will be dropped in Pennylane v0.44.
368382
Future versions of PennyLane are not guaranteed to work with TensorFlow.
369383
Instead, we recommend using the :doc:`JAX </introduction/interfaces/jax>` or :doc:`PyTorch </introduction/interfaces/torch>` interface for

pennylane/devices/device_api.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@
1616
"""
1717

1818
import abc
19+
import warnings
1920
from collections.abc import Iterable
2021
from dataclasses import replace
2122
from numbers import Number
2223
from typing import overload
2324

2425
import pennylane as qml
26+
from pennylane.exceptions import PennyLaneDeprecationWarning
2527
from pennylane.measurements import Shots
2628
from pennylane.tape import QuantumScript, QuantumScriptOrBatch
2729
from pennylane.tape.qscript import QuantumScriptBatch
@@ -187,6 +189,11 @@ def name(self) -> str:
187189
def __init__(self, wires=None, shots=None) -> None:
188190
# each instance should have its own Tracker.
189191
self.tracker = Tracker()
192+
if shots is not None and shots != Shots():
193+
warnings.warn(
194+
"Setting shots on device is deprecated. Please use the `set_shots` transform on the respective QNode instead.",
195+
PennyLaneDeprecationWarning,
196+
)
190197
self._shots = Shots(shots)
191198

192199
if wires is not None:

pennylane/devices/legacy_facade.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@
1616
new interface.
1717
"""
1818

19+
import warnings
20+
1921
# pylint: disable=not-callable
2022
from contextlib import contextmanager
2123
from copy import copy, deepcopy
2224
from dataclasses import replace
2325

2426
import pennylane as qml
25-
from pennylane.exceptions import DeviceError
27+
from pennylane.exceptions import DeviceError, PennyLaneDeprecationWarning
2628
from pennylane.math import get_canonical_interface_name, requires_grad
2729
from pennylane.measurements import MidMeasureMP, Shots
2830
from pennylane.transforms.core.transform_program import TransformProgram
@@ -167,6 +169,12 @@ def __init__(self, device: "qml.devices.LegacyDevice"):
167169
self._device = device
168170
self.config_filepath = getattr(self._device, "config_filepath", None)
169171

172+
if self._device.shots:
173+
warnings.warn(
174+
"Setting shots on device is deprecated. Please use the `set_shots` transform on the respective QNode instead.",
175+
PennyLaneDeprecationWarning,
176+
)
177+
170178
@property
171179
def tracker(self):
172180
"""A :class:`~pennylane.Tracker` that can store information about device executions, shots, batches,

pennylane/gradients/fisher.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ def circ(params):
387387
388388
"""
389389

390-
if device.shots or not isinstance(device, DefaultQubit):
390+
if tape.shots or not isinstance(device, DefaultQubit):
391391
tapes, processing_fn = metric_tensor(tape, *args, **kwargs)
392392

393393
def processing_fn_multiply(res):

pennylane/measurements/counts.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ def counts(
308308
all_outcomes=False,
309309
) -> CountsMP:
310310
r"""Sample from the supplied observable, with the number of shots
311-
determined from the ``dev.shots`` attribute of the corresponding device,
311+
determined from QNode,
312312
returning the number of counts for each sample. If no observable is provided then basis state
313313
samples are returned directly from the device.
314314

pennylane/measurements/sample.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ def sample(
191191
wires=None,
192192
) -> SampleMP:
193193
r"""Sample from the supplied observable, with the number of shots
194-
determined from the ``dev.shots`` attribute of the corresponding device,
194+
determined from QNode,
195195
returning raw samples. If no observable is provided then basis state samples are returned
196196
directly from the device.
197197

pennylane/optimize/shot_adaptive.py

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -284,22 +284,6 @@ def cost(*args, **kwargs):
284284

285285
return [np.concatenate(i) for i in zip(*grads)]
286286

287-
@staticmethod
288-
def check_device(dev):
289-
r"""Verifies that the device used by the objective function is non-analytic.
290-
291-
Args:
292-
dev (.devices.Device): the device to verify
293-
294-
Raises:
295-
ValueError: if the device is analytic
296-
"""
297-
if not dev.shots:
298-
raise ValueError(
299-
"The Rosalin optimizer can only be used with devices "
300-
"that estimate expectation values with a finite number of shots."
301-
)
302-
303287
def check_learning_rate(self, coeffs):
304288
r"""Verifies that the learning rate is less than 2 over the Lipschitz constant,
305289
where the Lipschitz constant is given by :math:`\sum |c_i|` for Hamiltonian
@@ -318,9 +302,12 @@ def check_learning_rate(self, coeffs):
318302

319303
def _single_shot_qnode_gradients(self, qnode, args, kwargs):
320304
"""Compute the single shot gradients of a QNode."""
321-
self.check_device(qnode.device)
322-
323305
tape = construct_tape(qnode)(*args, **kwargs)
306+
if not tape.shots:
307+
raise ValueError(
308+
"The Rosalin optimizer can only be used with qnodes "
309+
"that estimate expectation values with a finite number of shots."
310+
)
324311
[expval] = tape.measurements
325312
coeffs, observables = (
326313
expval.obs.terms()

pennylane/workflow/construct_batch.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,14 @@ def circuit(x):
446446

447447
def batch_constructor(*args, **kwargs) -> tuple[QuantumScriptBatch, PostprocessingFn]:
448448
"""Create a batch of tapes and a post processing function."""
449+
# Check if shots is being passed as parameter for deprecation warning
450+
if "shots" in kwargs:
451+
warnings.warn(
452+
"'shots' specified on call to a QNode is deprecated and will be removed in v0.44. Use qml.set_shots instead.",
453+
PennyLaneDeprecationWarning,
454+
stacklevel=2,
455+
)
456+
449457
if "shots" in kwargs and qnode._shots_override_device: # pylint: disable=protected-access
450458
warnings.warn(
451459
"Both 'shots=' parameter and 'set_shots' transform are specified. "

tests/capture/autograph/test_autograph.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -428,8 +428,9 @@ def circuit(x):
428428
)
429429
def test_mcm_one_shot(self, seed):
430430
"""Test if mcm one-shot miss transforms."""
431-
dev = qml.device("default.qubit", wires=5, shots=20, seed=seed)
431+
dev = qml.device("default.qubit", wires=5, seed=seed)
432432

433+
@qml.set_shots(20)
433434
@qml.qnode(dev, mcm_method="one-shot", postselect_mode="hw-like")
434435
def circ(x):
435436
qml.RX(x, wires=0)

0 commit comments

Comments
 (0)