Skip to content

Commit

Permalink
Deprecating Legacy Devices (#5997)
Browse files Browse the repository at this point in the history
Overview of deprecation changes:
- Added general fixture to `conftest.py` for capturing warnings. This
should capture any uncaptured warnings from the tests (read, the
deprecation warnings from the legacy devices), and therefore works as
expected and shouldn't cause any issues.
- Restructured interface tests: moved legacy tests to a separate folder,
pulled out tests in the `default.qubit` folder one level, and added
missing tests from the legacy tests to the DQ's tests. This should make
the removal process much easier by simply deleting a folder and pulling
a bunch of files up a directory.
- Updated some examples from the `pulse` module (and related misc.
files) that were relying on legacy devices and updated the code block
accordingly.
- Switched from `default.qubit.legacy` to `default.mixed` for tests
testing the old device interface, and not simply the legacy itself.

[sc-66694[](https://app.shortcut.com/xanaduai/story/66694)]

---------

Co-authored-by: Thomas R. Bromley <49409390+trbromley@users.noreply.github.com>
Co-authored-by: Mudit Pandey <mudit.pandey@xanadu.ai>
Co-authored-by: albi3ro <chrissie.c.l@gmail.com>
  • Loading branch information
4 people committed Jul 24, 2024
1 parent 4d16acb commit ad94334
Show file tree
Hide file tree
Showing 89 changed files with 16,418 additions and 13,993 deletions.
6 changes: 6 additions & 0 deletions doc/development/deprecations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ deprecations are listed below.
Pending deprecations
--------------------

* All of the legacy devices (any with the name ``default.qubit.{autograd,torch,tf,jax,legacy}``) are deprecated. Use ``default.qubit`` instead,
as it supports backpropagation for the many backends the legacy devices support.

- Deprecated in v0.38
- Will be removed in v0.39

* The ``decomp_depth`` argument in ``qml.device`` is deprecated.

- Deprecated in v0.38
Expand Down
4 changes: 4 additions & 0 deletions doc/releases/changelog-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,10 @@
Instead, use `pennylane.gradients.classical_fisher` and `pennylane.gradients.quantum_fisher`.
[(#5985)](https://github.com/PennyLaneAI/pennylane/pull/5985)

* The legacy devices `default.qubit.{autograd,torch,tf,jax,legacy}` are deprecated.
Instead, use `default.qubit` as it now supports backpropagation through the several backends.
[(#5997)](https://github.com/PennyLaneAI/pennylane/pull/5997)

<h3>Documentation 📝</h3>

* Improves the docstring for `QuantumScript.expand` and `qml.tape.tape.expand_tape`.
Expand Down
16 changes: 15 additions & 1 deletion pennylane/devices/default_qubit_autograd.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,15 @@
"""This module contains an autograd implementation of the :class:`~.DefaultQubitLegacy`
reference plugin.
"""
import warnings

from pennylane import PennyLaneDeprecationWarning
from pennylane import numpy as pnp
from pennylane.devices import DefaultQubitLegacy


class DefaultQubitAutograd(DefaultQubitLegacy):
"""Simulator plugin based on ``"default.qubit.legacy"``, written using Autograd.
r"""Simulator plugin based on ``"default.qubit.legacy"``, written using Autograd.
**Short name:** ``default.qubit.autograd``
Expand All @@ -34,6 +37,9 @@ class DefaultQubitAutograd(DefaultQubitLegacy):
pip install autograd
.. warning::
This device is deprecated. Use :class:`~pennylane.devices.DefaultQubit` instead; for example through ``qml.device("default.qubit")``, which now supports backpropagation.
**Example**
The ``default.qubit.autograd`` is designed to be used with end-to-end classical backpropagation
Expand Down Expand Up @@ -104,6 +110,14 @@ def _const_mul(constant, array):
return constant * array

def __init__(self, wires, *, shots=None, analytic=None):
warnings.warn(
f"Use of '{self.short_name}' is deprecated. Instead, use 'default.qubit', "
"which supports backpropagation. "
"If you experience issues, reach out to the PennyLane team on "
"the discussion forum: https://discuss.pennylane.ai/",
PennyLaneDeprecationWarning,
)

r_dtype = pnp.float64
c_dtype = pnp.complex128
super().__init__(wires, shots=shots, r_dtype=r_dtype, c_dtype=c_dtype, analytic=analytic)
Expand Down
15 changes: 14 additions & 1 deletion pennylane/devices/default_qubit_jax.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
"""This module contains a jax implementation of the :class:`~.DefaultQubitLegacy`
reference plugin.
"""
import warnings

# pylint: disable=ungrouped-imports
import numpy as np

Expand All @@ -34,7 +36,7 @@


class DefaultQubitJax(DefaultQubitLegacy):
"""Simulator plugin based on ``"default.qubit.legacy"``, written using jax.
r"""Simulator plugin based on ``"default.qubit.legacy"``, written using jax.
**Short name:** ``default.qubit.jax``
Expand All @@ -49,6 +51,9 @@ class DefaultQubitJax(DefaultQubitLegacy):
pip install jax jaxlib
.. warning::
This device is deprecated. Use :class:`~pennylane.devices.DefaultQubit` instead; for example through ``qml.device("default.qubit")``, which now supports backpropagation.
**Example**
The ``default.qubit.jax`` device is designed to be used with end-to-end classical backpropagation
Expand Down Expand Up @@ -165,6 +170,14 @@ def circuit():
operations = DefaultQubitLegacy.operations.union({"ParametrizedEvolution"})

def __init__(self, wires, *, shots=None, prng_key=None, analytic=None):
warnings.warn(
f"Use of '{self.short_name}' is deprecated. Instead, use 'default.qubit', "
"which supports backpropagation. "
"If you experience issues, reach out to the PennyLane team on "
"the discussion forum: https://discuss.pennylane.ai/",
qml.PennyLaneDeprecationWarning,
)

if jax.config.read("jax_enable_x64"):
c_dtype = jnp.complex128
r_dtype = jnp.float64
Expand Down
17 changes: 13 additions & 4 deletions pennylane/devices/default_qubit_legacy.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"""
import functools
import itertools
import warnings
from string import ascii_letters as ABC

import numpy as np
Expand Down Expand Up @@ -77,13 +78,13 @@ def _get_slice(index, axis, num_axes):

# pylint: disable=unused-argument
class DefaultQubitLegacy(QubitDevice):
"""Default qubit device for PennyLane.
r"""Default qubit device for PennyLane.
.. warning::
This is the legacy implementation of DefaultQubit. It has been replaced by
``qml.devices.DefaultQubit``, which can be accessed with the familiar constructor,
``qml.device("default.qubit")``.
This is the legacy implementation of DefaultQubit and is deprecated. It has been replaced by
:class:`~pennylane.devices.DefaultQubit`, which can be accessed with the familiar constructor,
``qml.device("default.qubit")``, and now supports backpropagation.
This change will not alter device behaviour for most workflows, but may have implications for
plugin developers and users who directly interact with device methods. Please consult
Expand Down Expand Up @@ -206,6 +207,14 @@ class DefaultQubitLegacy(QubitDevice):
def __init__(
self, wires, *, r_dtype=np.float64, c_dtype=np.complex128, shots=None, analytic=None
):
warnings.warn(
f"Use of '{self.short_name}' is deprecated. Instead, use 'default.qubit', "
"which supports backpropagation. "
"If you experience issues, reach out to the PennyLane team on "
"the discussion forum: https://discuss.pennylane.ai/",
qml.PennyLaneDeprecationWarning,
)

super().__init__(wires, shots, r_dtype=r_dtype, c_dtype=c_dtype, analytic=analytic)
self._debugger = None

Expand Down
14 changes: 13 additions & 1 deletion pennylane/devices/default_qubit_tf.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
reference plugin.
"""
import itertools
import warnings

import numpy as np
from packaging.version import Version
Expand Down Expand Up @@ -42,7 +43,7 @@


class DefaultQubitTF(DefaultQubitLegacy):
"""Simulator plugin based on ``"default.qubit.legacy"``, written using TensorFlow.
r"""Simulator plugin based on ``"default.qubit.legacy"``, written using TensorFlow.
**Short name:** ``default.qubit.tf``
Expand All @@ -57,6 +58,9 @@ class DefaultQubitTF(DefaultQubitLegacy):
pip install tensorflow>=2.0
.. warning::
This device is deprecated. Use :class:`~pennylane.devices.DefaultQubit` instead; for example through ``qml.device("default.qubit")``, which now supports backpropagation.
**Example**
The ``default.qubit.tf`` is designed to be used with end-to-end classical backpropagation
Expand Down Expand Up @@ -162,6 +166,14 @@ def _asarray(array, dtype=None):
return res

def __init__(self, wires, *, shots=None, analytic=None):
warnings.warn(
f"Use of '{self.short_name}' is deprecated. Instead, use 'default.qubit', "
"which supports backpropagation. "
"If you experience issues, reach out to the PennyLane team on "
"the discussion forum: https://discuss.pennylane.ai/",
qml.PennyLaneDeprecationWarning,
)

r_dtype = tf.float64
c_dtype = tf.complex128

Expand Down
14 changes: 13 additions & 1 deletion pennylane/devices/default_qubit_torch.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@

import numpy as np

from pennylane import PennyLaneDeprecationWarning
from pennylane.ops.qubit.attributes import diagonal_in_z_basis

from . import DefaultQubitLegacy
Expand All @@ -43,7 +44,7 @@


class DefaultQubitTorch(DefaultQubitLegacy):
"""Simulator plugin based on ``"default.qubit.legacy"``, written using PyTorch.
r"""Simulator plugin based on ``"default.qubit.legacy"``, written using PyTorch.
**Short name:** ``default.qubit.torch``
Expand All @@ -58,6 +59,10 @@ class DefaultQubitTorch(DefaultQubitLegacy):
pip install torch>=1.8.0
.. warning::
This device is deprecated. Use :class:`~pennylane.devices.DefaultQubit` instead; for example through ``qml.device("default.qubit")``, which now supports backpropagation.
**Example**
The ``default.qubit.torch`` is designed to be used with end-to-end classical backpropagation
Expand Down Expand Up @@ -165,6 +170,13 @@ def circuit(x):
_ndim = staticmethod(lambda tensor: tensor.ndim)

def __init__(self, wires, *, shots=None, analytic=None, torch_device=None):
warnings.warn(
f"Use of '{self.short_name}' is deprecated. Instead, use 'default.qubit', "
"which supports backpropagation. "
"If you experience issues, reach out to the PennyLane team on "
"the discussion forum: https://discuss.pennylane.ai/",
PennyLaneDeprecationWarning,
)
# Store if the user specified a Torch device. Otherwise the execute
# method attempts to infer the Torch device from the gate parameters.
self._torch_device_specified = torch_device is not None
Expand Down
2 changes: 0 additions & 2 deletions pennylane/devices/qubit/simulate.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,6 @@ def measure_final_state(circuit, state, is_state_batched, **execution_kwargs) ->
mid_measurements = execution_kwargs.get("mid_measurements", None)

# analytic case

if not circuit.shots:
if mid_measurements is not None:
raise TypeError("Native mid-circuit measurements are only supported with finite shots.")
Expand All @@ -243,7 +242,6 @@ def measure_final_state(circuit, state, is_state_batched, **execution_kwargs) ->
)

# finite-shot case

rng = default_rng(rng)
results = measure_with_samples(
circuit.measurements,
Expand Down
1 change: 1 addition & 0 deletions pennylane/drawer/tape_mpl.py
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,7 @@ def tape_mpl(
if update_style := (has_mpl and style != "rcParams"):
restore_params = mpl.rcParams.copy()
_set_style(style)

try:
return _tape_mpl(
tape,
Expand Down
2 changes: 1 addition & 1 deletion pennylane/gradients/pulse_gradient.py
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ def stoch_pulse_grad(
jax.config.update("jax_enable_x64", True)
dev = qml.device("default.qubit.jax")
dev = qml.device("default.qubit")
def sin(p, t):
return jax.numpy.sin(p * t)
Expand Down
2 changes: 1 addition & 1 deletion pennylane/gradients/pulse_gradient_odegen.py
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,7 @@ def pulse_odegen(
.. code-block:: python
dev = qml.device("default.qubit.jax")
dev = qml.device("default.qubit")
@qml.qnode(dev, interface="jax", diff_method=qml.gradients.pulse_odegen)
def circuit(params):
Expand Down
15 changes: 9 additions & 6 deletions pennylane/ops/functions/evolve.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,10 @@ def evolve(*args, **kwargs): # pylint: disable=unused-argument
import jax
dev = qml.device("default.qubit.jax", wires=4)
jax.config.update("jax_enable_x64", True)
dev = qml.device("default.qubit")
@jax.jit
@qml.qnode(dev, interface="jax")
def circuit(params):
Expand All @@ -138,13 +141,13 @@ def circuit(params):
>>> params = [1., 2., 3., 4.]
>>> circuit(params)
Array(0.8627419, dtype=float32)
Array(0.86231063, dtype=float64)
>>> jax.grad(circuit)(params)
[Array(50.690746, dtype=float32),
Array(-6.296886e-05, dtype=float32),
Array(-6.3341584e-05, dtype=float32),
Array(-7.052516e-05, dtype=float32)]
[Array(50.391273, dtype=float64),
Array(-9.42415807e-05, dtype=float64),
Array(-0.0001049, dtype=float64),
Array(-0.00010601, dtype=float64)]
.. note::
In the example above, the decorator ``@jax.jit`` is used to compile this execution just-in-time. This means
Expand Down
8 changes: 5 additions & 3 deletions pennylane/pulse/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,9 @@
import jax
dev = qml.device("default.qubit.jax", wires=1)
jax.config.update("jax_enable_x64", True)
dev = qml.device("default.qubit", wires=1)
@jax.jit
@qml.qnode(dev, interface="jax")
Expand All @@ -246,10 +248,10 @@ def circuit(params):
>>> params = [1.2]
>>> circuit(params)
Array(0.96632576, dtype=float32)
Array(0.96632722, dtype=float64)
>>> jax.grad(circuit)(params)
[Array(2.3569832, dtype=float32)]
[Array(2.35694829, dtype=float64)]
We can use the decorator ``jax.jit`` to compile this execution just-in-time. This means the first execution
will typically take a little longer with the benefit that all following executions will be significantly faster.
Expand Down
13 changes: 9 additions & 4 deletions pennylane/pulse/convenience_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

# pylint: disable=unused-argument
def constant(scalar, time):
"""Returns the given ``scalar``, for use in defining a :class:`~.ParametrizedHamiltonian` with a
r"""Returns the given ``scalar``, for use in defining a :class:`~.ParametrizedHamiltonian` with a
trainable coefficient.
Args:
Expand Down Expand Up @@ -58,7 +58,12 @@ def constant(scalar, time):
.. code-block:: python
dev = qml.device("default.qubit.jax", wires=1)
import jax
jax.config.update("jax_enable_x64", True)
dev = qml.device("default.qubit")
@qml.qnode(dev, interface="jax")
def circuit(params):
qml.evolve(H)(params, t=2)
Expand All @@ -67,10 +72,10 @@ def circuit(params):
>>> params = jnp.array([5.0])
>>> circuit(params)
Array(0.40808904, dtype=float32)
Array(0.40808193, dtype=float64)
>>> jax.grad(circuit)(params)
Array([-3.6517754], dtype=float32)
Array([-3.65178003], dtype=float64)
"""
return scalar

Expand Down
Loading

0 comments on commit ad94334

Please sign in to comment.