Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove decomp_depth from qml.device constructor #6234

Merged
merged 17 commits into from
Sep 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions doc/development/deprecations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,6 @@ Pending deprecations
- Deprecated in v0.39
- Will be removed in v0.40

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

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

* The ``simplify`` argument in ``qml.Hamiltonian`` and ``qml.ops.LinearCombination`` is deprecated.
Instead, ``qml.simplify()`` can be called on the constructed operator.

Expand Down Expand Up @@ -106,6 +101,11 @@ Other deprecations
Completed deprecation cycles
----------------------------

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

- Deprecated in v0.38
- Removed in v0.39

* The functions ``qml.qinfo.classical_fisher`` and ``qml.qinfo.quantum_fisher`` have been removed and migrated to the ``qml.gradients``
module. Therefore, ``qml.gradients.classical_fisher`` and ``qml.gradients.quantum_fisher`` should be used instead.

Expand Down
3 changes: 3 additions & 0 deletions doc/releases/changelog-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@
Please use `qml.transforms.split_non_commuting` instead.
[(#6204)](https://github.com/PennyLaneAI/pennylane/pull/6204)

* The `decomp_depth` keyword argument to `qml.device` is removed.
albi3ro marked this conversation as resolved.
Show resolved Hide resolved
[(#6234)](https://github.com/PennyLaneAI/pennylane/pull/6234)

* `Operator.expand` is now removed. Use `qml.tape.QuantumScript(op.deocomposition())` instead.
[(#6227)](https://github.com/PennyLaneAI/pennylane/pull/6227)

Expand Down
43 changes: 13 additions & 30 deletions pennylane/devices/device_constructor.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
"""
This module contains code for the main device construction delegation logic.
"""
import warnings
from importlib import metadata
from sys import version_info

Expand Down Expand Up @@ -57,8 +56,7 @@ def refresh_devices():

# pylint: disable=protected-access
def device(name, *args, **kwargs):
r"""
Load a device and return the instance.
r"""Load a device and return the instance.

This function is used to load a particular quantum device,
which can then be used to construct QNodes.
Expand Down Expand Up @@ -105,12 +103,6 @@ def device(name, *args, **kwargs):
that contains global and/or device specific configurations.
custom_decomps (Dict[Union(str, Operator), Callable]): Custom
decompositions to be applied by the device at runtime.
decomp_depth (int): For when custom decompositions are specified,
the maximum expansion depth used by the expansion function.

.. warning::

The ``decomp_depth`` argument is deprecated and will be removed in version 0.39.

All devices must be loaded by specifying their **short-name** as listed above,
followed by the **wires** (subsystems) you wish to initialize. The ``wires``
Expand All @@ -122,10 +114,10 @@ def device(name, *args, **kwargs):
dev = qml.device('default.qubit', wires=5)

def circuit():
qml.Hadamard(wires=1)
qml.Hadamard(wires=[0])
qml.CNOT(wires=[3, 4])
...
qml.Hadamard(wires=1)
qml.Hadamard(wires=[0])
qml.CNOT(wires=[3, 4])
...

The ``wires`` argument can also be a sequence of unique numbers or strings, specifying custom wire labels
that the user employs to address the wires:
Expand All @@ -135,10 +127,10 @@ def circuit():
dev = qml.device('default.qubit', wires=['ancilla', 'q11', 'q12', -1, 1])

def circuit():
qml.Hadamard(wires='q11')
qml.Hadamard(wires=['ancilla'])
qml.CNOT(wires=['q12', -1])
...
qml.Hadamard(wires='q11')
qml.Hadamard(wires=['ancilla'])
qml.CNOT(wires=['q12', -1])
...

On some newer devices, such as ``default.qubit``, the ``wires`` argument can be omitted altogether,
and instead the wires will be computed when executing a circuit depending on its contents.
Expand All @@ -157,8 +149,8 @@ def circuit():

@qml.qnode(dev)
def circuit(a):
qml.RX(a, wires=0)
return qml.sample(qml.Z(0))
qml.RX(a, wires=0)
return qml.sample(qml.Z(0))

>>> circuit(0.8) # 10 samples are returned
array([ 1, 1, 1, 1, -1, 1, 1, -1, 1, 1])
Expand Down Expand Up @@ -243,15 +235,6 @@ def run_cnot():
# Pop the custom decomposition keyword argument; we will use it here
# only and not pass it to the device.
custom_decomps = kwargs.pop("custom_decomps", None)
decomp_depth = kwargs.pop("decomp_depth", None)

if decomp_depth is not None:
warnings.warn(
"The decomp_depth argument is deprecated and will be removed in version 0.39. ",
qml.PennyLaneDeprecationWarning,
)
else:
decomp_depth = 10

kwargs.pop("config", None)
options.update(kwargs)
Expand Down Expand Up @@ -284,12 +267,12 @@ def _safe_specifier_set(version_str):
if custom_decomps is not None:
if isinstance(dev, qml.devices.LegacyDevice):
custom_decomp_expand_fn = qml.transforms.create_decomp_expand_fn(
custom_decomps, dev, decomp_depth=decomp_depth
custom_decomps, dev, decomp_depth=10
)
dev.custom_expand(custom_decomp_expand_fn)
else:
custom_decomp_preprocess = qml.transforms.tape_expand._create_decomp_preprocessing(
custom_decomps, dev, decomp_depth=decomp_depth
custom_decomps, dev, decomp_depth=10
)
dev.preprocess = custom_decomp_preprocess

Expand Down
9 changes: 0 additions & 9 deletions tests/devices/test_legacy_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -1074,15 +1074,6 @@ def test_shot_vector_property(self):

assert dev.shots.total_shots == 22

def test_decomp_depth_is_deprecated(self):
"""Test that a warning is raised when using the deprecated decomp_depth argument"""

with pytest.warns(
qml.PennyLaneDeprecationWarning,
match="The decomp_depth argument is deprecated",
):
qml.device("default.qubit", decomp_depth=1)


class TestBatchExecution:
"""Tests for the batch_execute method."""
Expand Down
70 changes: 0 additions & 70 deletions tests/transforms/test_tape_expand.py
Original file line number Diff line number Diff line change
Expand Up @@ -539,30 +539,6 @@ def circuit():

assert decomp_ops[2].name == "CNOT"

@pytest.mark.parametrize("device_name", ["default.qubit", "default.qubit.legacy"])
def test_no_decomp_with_depth_zero(self, device_name):
"""Test that specifying a single custom decomposition works as expected."""

custom_decomps = {"Hadamard": custom_hadamard, "CNOT": custom_cnot}
with pytest.warns(
qml.PennyLaneDeprecationWarning, match="The decomp_depth argument is deprecated"
):
decomp_dev = qml.device(
device_name, wires=2, custom_decomps=custom_decomps, decomp_depth=0
)

@qml.qnode(decomp_dev)
def circuit():
qml.Hadamard(wires=0)
qml.CNOT(wires=[0, 1])
return qml.expval(qml.PauliZ(0))

decomp_ops = qml.workflow.construct_batch(circuit, level=None)()[0][0].operations

assert len(decomp_ops) == 2
assert decomp_ops[0].name == "Hadamard"
assert decomp_ops[1].name == "CNOT"

@pytest.mark.parametrize("device_name", ["default.qubit", "default.qubit.legacy"])
def test_one_custom_decomp_gradient(self, device_name):
"""Test that gradients are still correctly computed after a decomposition
Expand Down Expand Up @@ -713,52 +689,6 @@ def circuit():
assert decomp_ops[4].name == "CNOT"
assert decomp_ops[4].wires == Wires([0, 1])

@pytest.mark.parametrize("device_name", ["default.qubit", "default.qubit.legacy"])
def test_custom_decomp_different_depth(self, device_name):
"""Test that alternative expansion depths can be specified."""

# BasicEntanglerLayers custom decomposition involves AngleEmbedding. If
# expansion depth is 2, the AngleEmbedding will still be decomposed into
# RX (since it's not a supported operation on the device), but the RX will
# not be further decomposed even though the custom decomposition is specified.
custom_decomps = {"BasicEntanglerLayers": custom_basic_entangler_layers, "RX": custom_rx}

with pytest.warns(
qml.PennyLaneDeprecationWarning, match="The decomp_depth argument is deprecated"
):
decomp_dev_2 = qml.device(
device_name, wires=2, custom_decomps=custom_decomps, decomp_depth=2
)

decomp_dev_3 = qml.device(
device_name, wires=2, custom_decomps=custom_decomps, decomp_depth=3
)

def circuit():
qml.BasicEntanglerLayers([[0.1, 0.2]], wires=[0, 1])
return qml.expval(qml.PauliZ(0))

circuit2 = qml.QNode(circuit, decomp_dev_2)
circuit3 = qml.QNode(circuit, decomp_dev_3)

decomp_ops = qml.workflow.construct_batch(circuit2, level=None)()[0][0].operations

assert len(decomp_ops) == 3

assert decomp_ops[0].name == "RX"
assert np.isclose(decomp_ops[0].parameters[0], 0.1)
assert decomp_ops[0].wires == Wires(0)

assert decomp_ops[1].name == "RX"
assert np.isclose(decomp_ops[1].parameters[0], 0.2)
assert decomp_ops[1].wires == Wires(1)

assert decomp_ops[2].name == "CNOT"
assert decomp_ops[2].wires == Wires([0, 1])

decomp_ops = qml.workflow.construct_batch(circuit3, level=None)()[0][0].operations
assert len(decomp_ops) == 5

@pytest.mark.parametrize("device_name", ["default.qubit", "default.qubit.legacy"])
def test_custom_decomp_with_adjoint(self, device_name):
"""Test that applying an adjoint in the circuit results in the adjoint
Expand Down
Loading