From 95251e86815e935138772ad0150f7c2c2cbb863b Mon Sep 17 00:00:00 2001 From: albi3ro Date: Fri, 6 Sep 2024 09:32:30 -0400 Subject: [PATCH 01/11] remove decomp depth --- doc/development/deprecations.rst | 10 +- doc/releases/changelog-dev.md | 2 + pennylane/devices/device_constructor.py | 264 +++++++++++------------- 3 files changed, 131 insertions(+), 145 deletions(-) diff --git a/doc/development/deprecations.rst b/doc/development/deprecations.rst index 1735f59a270..714913e2fe9 100644 --- a/doc/development/deprecations.rst +++ b/doc/development/deprecations.rst @@ -21,11 +21,6 @@ Pending deprecations - Deprecated in v0.38 - Will be removed in v0.39 -* The ``decomp_depth`` argument in ``qml.device`` is deprecated. - - - Deprecated in v0.38 - - Will be removed in v0.39 - * The ``max_expansion`` argument in ``qml.QNode`` is deprecated. - Deprecated in v0.38 @@ -123,6 +118,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.transforms.sum_expand`` and ``qml.transforms.hamiltonian_expand`` are deprecated. Instead, ``qml.transforms.split_non_commuting`` can be used for equivalent behaviour. diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md index 2d0352fffa5..22ef1d6046b 100644 --- a/doc/releases/changelog-dev.md +++ b/doc/releases/changelog-dev.md @@ -25,6 +25,8 @@ * `qml.transforms.hamiltonian_expand` and `qml.transforms.sum_expand` are removed. Please use `qml.transforms.split_non_commuting` instead. +* The `decomp_depth` keyword argument to `qml.device` is removed. +

Deprecations πŸ‘‹

Documentation πŸ“

diff --git a/pennylane/devices/device_constructor.py b/pennylane/devices/device_constructor.py index 0f9d274ea4a..490aa891ce1 100644 --- a/pennylane/devices/device_constructor.py +++ b/pennylane/devices/device_constructor.py @@ -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 @@ -58,167 +57,161 @@ def refresh_devices(): # pylint: disable=protected-access def device(name, *args, **kwargs): r""" - Load a device and return the instance. + 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. + This function is used to load a particular quantum device, + which can then be used to construct QNodes. - PennyLane comes with support for the following devices: + PennyLane comes with support for the following devices: - * :mod:`'default.qubit' `: a simple - state simulator of qubit-based quantum circuit architectures. + * :mod:`'default.qubit' `: a simple + state simulator of qubit-based quantum circuit architectures. - * :mod:`'default.mixed' `: a mixed-state - simulator of qubit-based quantum circuit architectures. + * :mod:`'default.mixed' `: a mixed-state + simulator of qubit-based quantum circuit architectures. - * ``'lightning.qubit'``: a more performant state simulator of qubit-based - quantum circuit architectures written in C++. + * ``'lightning.qubit'``: a more performant state simulator of qubit-based + quantum circuit architectures written in C++. - * :mod:`'default.qutrit' `: a simple - state simulator of qutrit-based quantum circuit architectures. + * :mod:`'default.qutrit' `: a simple + state simulator of qutrit-based quantum circuit architectures. - * :mod:`'default.qutrit.mixed' `: a - mixed-state simulator of qutrit-based quantum circuit architectures. + * :mod:`'default.qutrit.mixed' `: a + mixed-state simulator of qutrit-based quantum circuit architectures. - * :mod:`'default.gaussian' `: a simple simulator - of Gaussian states and operations on continuous-variable circuit architectures. + * :mod:`'default.gaussian' `: a simple simulator + of Gaussian states and operations on continuous-variable circuit architectures. - * :mod:`'default.clifford' `: an efficient - simulator of Clifford circuits. + * :mod:`'default.clifford' `: an efficient + simulator of Clifford circuits. - * :mod:`'default.tensor' `: a simulator - of quantum circuits based on tensor networks. + * :mod:`'default.tensor' `: a simulator + of quantum circuits based on tensor networks. - Additional devices are supported through plugins β€” see - the `available plugins `_ for more - details. To list all currently installed devices, run - :func:`qml.about `. + Additional devices are supported through plugins β€” see + the `available plugins `_ for more + details. To list all currently installed devices, run + :func:`qml.about `. - Args: - name (str): the name of the device to load - wires (int): the number of wires (subsystems) to initialise - the device with. Note that this is optional for certain - devices, such as ``default.qubit`` + Args: + name (str): the name of the device to load + wires (int): the number of wires (subsystems) to initialise + the device with. Note that this is optional for certain + devices, such as ``default.qubit`` - Keyword Args: - config (pennylane.Configuration): a PennyLane configuration object - 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. + Keyword Args: + config (pennylane.Configuration): a PennyLane configuration object + 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. - .. warning:: + All devices must be loaded by specifying their **short-name** as listed above, + followed by the **wires** (subsystems) you wish to initialize. The ``wires`` + argument can be an integer, in which case the wires of the device are addressed + by consecutive integers: - The ``decomp_depth`` argument is deprecated and will be removed in version 0.39. + .. code-block:: python - All devices must be loaded by specifying their **short-name** as listed above, - followed by the **wires** (subsystems) you wish to initialize. The ``wires`` - argument can be an integer, in which case the wires of the device are addressed - by consecutive integers: + dev = qml.device('default.qubit', wires=5) - .. code-block:: python + def circuit(): + qml.Hadamard(wires=1) + qml.Hadamard(wires=[0]) + qml.CNOT(wires=[3, 4]) + ... - dev = qml.device('default.qubit', wires=5) + 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: - def circuit(): - qml.Hadamard(wires=1) - qml.Hadamard(wires=[0]) - qml.CNOT(wires=[3, 4]) - ... + .. code-block:: python - 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: + dev = qml.device('default.qubit', wires=['ancilla', 'q11', 'q12', -1, 1]) - .. code-block:: python + def circuit(): + ` qml.Hadamard(wires='q11') + qml.Hadamard(wires=['ancilla']) + qml.CNOT(wires=['q12', -1]) + ...` - dev = qml.device('default.qubit', wires=['ancilla', 'q11', 'q12', -1, 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. - def circuit(): - qml.Hadamard(wires='q11') - qml.Hadamard(wires=['ancilla']) - qml.CNOT(wires=['q12', -1]) - ... + >>> dev = qml.device("default.qubit") - 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. + Most devices accept a ``shots`` argument which specifies how many circuit executions + are used to estimate stochastic return values. As an example, ``qml.sample()`` measurements + will return as many samples as specified in the shots argument. The shots argument can be + changed on a per-call basis using the built-in ``shots`` keyword argument. Note that the + ``shots`` argument can be a single integer or a list of shot values. - >>> dev = qml.device("default.qubit") + .. code-block:: python - Most devices accept a ``shots`` argument which specifies how many circuit executions - are used to estimate stochastic return values. As an example, ``qml.sample()`` measurements - will return as many samples as specified in the shots argument. The shots argument can be - changed on a per-call basis using the built-in ``shots`` keyword argument. Note that the - ``shots`` argument can be a single integer or a list of shot values. + dev = qml.device('default.qubit', wires=1, shots=10) - .. code-block:: python + @qml.qnode(dev) + def circuit(a): + qml.RX(a, wires=0) + return qml.sample(qml.Z(0)) - dev = qml.device('default.qubit', wires=1, shots=10) + >>> circuit(0.8) # 10 samples are returned + array([ 1, 1, 1, 1, -1, 1, 1, -1, 1, 1]) + >>> circuit(0.8, shots=[3, 4, 4]) # default is overwritten for this call + (array([1, 1, 1]), array([ 1, -1, 1, 1]), array([1, 1, 1, 1])) + >>> circuit(0.8) # back to default of 10 samples + array([ 1, -1, 1, 1, -1, 1, 1, 1, 1, 1]) - @qml.qnode(dev) - def circuit(a): - qml.RX(a, wires=0) - return qml.sample(qml.Z(0)) + When constructing a device, we may optionally pass a dictionary of custom + decompositions to be applied to certain operations upon device execution. + This is useful for enabling support of gates on devices where they would normally + be unsupported. - >>> circuit(0.8) # 10 samples are returned - array([ 1, 1, 1, 1, -1, 1, 1, -1, 1, 1]) - >>> circuit(0.8, shots=[3, 4, 4]) # default is overwritten for this call - (array([1, 1, 1]), array([ 1, -1, 1, 1]), array([1, 1, 1, 1])) - >>> circuit(0.8) # back to default of 10 samples - array([ 1, -1, 1, 1, -1, 1, 1, 1, 1, 1]) + For example, suppose we are running on an ion trap device which does not + natively implement the CNOT gate, but we would still like to write our + circuits in terms of CNOTs. On a ion trap device, CNOT can be implemented + using the ``IsingXX`` gate. We first define a decomposition function + (such functions have the signature ``decomposition(*params, wires)``): + + .. code-block:: python - When constructing a device, we may optionally pass a dictionary of custom - decompositions to be applied to certain operations upon device execution. - This is useful for enabling support of gates on devices where they would normally - be unsupported. - - For example, suppose we are running on an ion trap device which does not - natively implement the CNOT gate, but we would still like to write our - circuits in terms of CNOTs. On a ion trap device, CNOT can be implemented - using the ``IsingXX`` gate. We first define a decomposition function - (such functions have the signature ``decomposition(*params, wires)``): - - .. code-block:: python - - def ion_trap_cnot(wires, **_): - return [ - qml.RY(np.pi/2, wires=wires[0]), - qml.IsingXX(np.pi/2, wires=wires), - qml.RX(-np.pi/2, wires=wires[0]), - qml.RY(-np.pi/2, wires=wires[0]), - qml.RY(-np.pi/2, wires=wires[1]) - ] - - Next, we create a device, and a QNode for testing. When constructing the - QNode, we can set the expansion strategy to ``"device"`` to ensure the - decomposition is applied and will be viewable when we draw the circuit. - Note that custom decompositions should accept keyword arguments even when - it is not used. - - .. code-block:: python - - # As the CNOT gate normally has no decomposition, we can use default.qubit - # here for expository purposes. - dev = qml.device( - 'default.qubit', wires=2, custom_decomps={"CNOT" : ion_trap_cnot} - ) - - @qml.qnode(dev, expansion_strategy="device") - def run_cnot(): - qml.CNOT(wires=[0, 1]) - return qml.expval(qml.X(1)) + def ion_trap_cnot(wires, **_): + return [ + qml.RY(np.pi/2, wires=wires[0]), + qml.IsingXX(np.pi/2, wires=wires), + qml.RX(-np.pi/2, wires=wires[0]), + qml.RY(-np.pi/2, wires=wires[0]), + qml.RY(-np.pi/2, wires=wires[1]) + ] + + Next, we create a device, and a QNode for testing. When constructing the + QNode, we can set the expansion strategy to ``"device"`` to ensure the + decomposition is applied and will be viewable when we draw the circuit. + Note that custom decompositions should accept keyword arguments even when + it is not used. + + .. code-block:: python + + # As the CNOT gate normally has no decomposition, we can use default.qubit + # here for expository purposes. + dev = qml.device( + 'default.qubit', wires=2, custom_decomps={"CNOT" : ion_trap_cnot} + ) + + @qml.qnode(dev, expansion_strategy="device") + def run_cnot(): + qml.CNOT(wires=[0, 1]) + return qml.expval(qml.X(1)) + + >>> print(qml.draw(run_cnot)()) + 0: ──RY(1.57)─╭IsingXX(1.57)──RX(-1.57)──RY(-1.57)── + 1: ───────────╰IsingXX(1.57)──RY(-1.57)───────────── - >>> print(qml.draw(run_cnot)()) - 0: ──RY(1.57)─╭IsingXX(1.57)──RX(-1.57)──RY(-1.57)── - 1: ───────────╰IsingXX(1.57)──RY(-1.57)───────────── - - Some devices may accept additional arguments. For instance, - ``default.gaussian`` accepts the keyword argument ``hbar``, to set - the convention used in the commutation relation :math:`[\x,\p]=i\hbar` - (by default set to 2). + Some devices may accept additional arguments. For instance, + ``default.gaussian`` accepts the keyword argument ``hbar``, to set + the convention used in the commutation relation :math:`[\x,\p]=i\hbar` + (by default set to 2). - Please refer to the documentation for the individual devices to see any - additional arguments that might be required or supported. + Please refer to the documentation for the individual devices to see any + additional arguments that might be required or supported. """ if name not in plugin_devices: # Device does not exist in the loaded device list. @@ -243,15 +236,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) @@ -284,12 +268,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 From e8656ad57cdb34dfe77cdcedac8978f0da619bc5 Mon Sep 17 00:00:00 2001 From: albi3ro Date: Fri, 6 Sep 2024 09:37:58 -0400 Subject: [PATCH 02/11] oops --- pennylane/devices/device_constructor.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pennylane/devices/device_constructor.py b/pennylane/devices/device_constructor.py index 490aa891ce1..a377ea3aa0e 100644 --- a/pennylane/devices/device_constructor.py +++ b/pennylane/devices/device_constructor.py @@ -115,10 +115,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: From c739b6387d74ce6ed6df0f46f542c96920341bd1 Mon Sep 17 00:00:00 2001 From: albi3ro Date: Fri, 6 Sep 2024 11:13:33 -0400 Subject: [PATCH 03/11] oops again --- pennylane/devices/device_constructor.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pennylane/devices/device_constructor.py b/pennylane/devices/device_constructor.py index a377ea3aa0e..15af65d1741 100644 --- a/pennylane/devices/device_constructor.py +++ b/pennylane/devices/device_constructor.py @@ -65,28 +65,28 @@ def device(name, *args, **kwargs): PennyLane comes with support for the following devices: * :mod:`'default.qubit' `: a simple - state simulator of qubit-based quantum circuit architectures. + state simulator of qubit-based quantum circuit architectures. * :mod:`'default.mixed' `: a mixed-state - simulator of qubit-based quantum circuit architectures. + simulator of qubit-based quantum circuit architectures. * ``'lightning.qubit'``: a more performant state simulator of qubit-based - quantum circuit architectures written in C++. + quantum circuit architectures written in C++. * :mod:`'default.qutrit' `: a simple - state simulator of qutrit-based quantum circuit architectures. + state simulator of qutrit-based quantum circuit architectures. * :mod:`'default.qutrit.mixed' `: a - mixed-state simulator of qutrit-based quantum circuit architectures. + mixed-state simulator of qutrit-based quantum circuit architectures. * :mod:`'default.gaussian' `: a simple simulator - of Gaussian states and operations on continuous-variable circuit architectures. + of Gaussian states and operations on continuous-variable circuit architectures. * :mod:`'default.clifford' `: an efficient - simulator of Clifford circuits. + simulator of Clifford circuits. * :mod:`'default.tensor' `: a simulator - of quantum circuits based on tensor networks. + of quantum circuits based on tensor networks. Additional devices are supported through plugins β€” see the `available plugins `_ for more From 466b8e29beca9ef446d670dd615b196197d6fdef Mon Sep 17 00:00:00 2001 From: albi3ro Date: Fri, 6 Sep 2024 11:15:59 -0400 Subject: [PATCH 04/11] oops again --- pennylane/devices/device_constructor.py | 251 ++++++++++++------------ 1 file changed, 125 insertions(+), 126 deletions(-) diff --git a/pennylane/devices/device_constructor.py b/pennylane/devices/device_constructor.py index 15af65d1741..4c1468420ce 100644 --- a/pennylane/devices/device_constructor.py +++ b/pennylane/devices/device_constructor.py @@ -56,162 +56,161 @@ 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. + This function is used to load a particular quantum device, + which can then be used to construct QNodes. - PennyLane comes with support for the following devices: + PennyLane comes with support for the following devices: - * :mod:`'default.qubit' `: a simple - state simulator of qubit-based quantum circuit architectures. + * :mod:`'default.qubit' `: a simple + state simulator of qubit-based quantum circuit architectures. - * :mod:`'default.mixed' `: a mixed-state - simulator of qubit-based quantum circuit architectures. + * :mod:`'default.mixed' `: a mixed-state + simulator of qubit-based quantum circuit architectures. - * ``'lightning.qubit'``: a more performant state simulator of qubit-based - quantum circuit architectures written in C++. + * ``'lightning.qubit'``: a more performant state simulator of qubit-based + quantum circuit architectures written in C++. - * :mod:`'default.qutrit' `: a simple - state simulator of qutrit-based quantum circuit architectures. + * :mod:`'default.qutrit' `: a simple + state simulator of qutrit-based quantum circuit architectures. - * :mod:`'default.qutrit.mixed' `: a - mixed-state simulator of qutrit-based quantum circuit architectures. + * :mod:`'default.qutrit.mixed' `: a + mixed-state simulator of qutrit-based quantum circuit architectures. - * :mod:`'default.gaussian' `: a simple simulator - of Gaussian states and operations on continuous-variable circuit architectures. + * :mod:`'default.gaussian' `: a simple simulator + of Gaussian states and operations on continuous-variable circuit architectures. - * :mod:`'default.clifford' `: an efficient - simulator of Clifford circuits. + * :mod:`'default.clifford' `: an efficient + simulator of Clifford circuits. - * :mod:`'default.tensor' `: a simulator - of quantum circuits based on tensor networks. + * :mod:`'default.tensor' `: a simulator + of quantum circuits based on tensor networks. - Additional devices are supported through plugins β€” see - the `available plugins `_ for more - details. To list all currently installed devices, run - :func:`qml.about `. + Additional devices are supported through plugins β€” see + the `available plugins `_ for more + details. To list all currently installed devices, run + :func:`qml.about `. - Args: - name (str): the name of the device to load - wires (int): the number of wires (subsystems) to initialise - the device with. Note that this is optional for certain - devices, such as ``default.qubit`` + Args: + name (str): the name of the device to load + wires (int): the number of wires (subsystems) to initialise + the device with. Note that this is optional for certain + devices, such as ``default.qubit`` - Keyword Args: - config (pennylane.Configuration): a PennyLane configuration object - 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. + Keyword Args: + config (pennylane.Configuration): a PennyLane configuration object + 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. - All devices must be loaded by specifying their **short-name** as listed above, - followed by the **wires** (subsystems) you wish to initialize. The ``wires`` - argument can be an integer, in which case the wires of the device are addressed - by consecutive integers: + All devices must be loaded by specifying their **short-name** as listed above, + followed by the **wires** (subsystems) you wish to initialize. The ``wires`` + argument can be an integer, in which case the wires of the device are addressed + by consecutive integers: - .. code-block:: python + .. code-block:: python - dev = qml.device('default.qubit', wires=5) + dev = qml.device('default.qubit', wires=5) - def circuit(): - qml.Hadamard(wires=1) - qml.Hadamard(wires=[0]) - qml.CNOT(wires=[3, 4]) - ... + def circuit(): + 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: + 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: - .. code-block:: python + .. code-block:: python - dev = qml.device('default.qubit', wires=['ancilla', 'q11', 'q12', -1, 1]) + 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]) - ...` + def circuit(): +` 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. + 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. - >>> dev = qml.device("default.qubit") + >>> dev = qml.device("default.qubit") - Most devices accept a ``shots`` argument which specifies how many circuit executions - are used to estimate stochastic return values. As an example, ``qml.sample()`` measurements - will return as many samples as specified in the shots argument. The shots argument can be - changed on a per-call basis using the built-in ``shots`` keyword argument. Note that the - ``shots`` argument can be a single integer or a list of shot values. + Most devices accept a ``shots`` argument which specifies how many circuit executions + are used to estimate stochastic return values. As an example, ``qml.sample()`` measurements + will return as many samples as specified in the shots argument. The shots argument can be + changed on a per-call basis using the built-in ``shots`` keyword argument. Note that the + ``shots`` argument can be a single integer or a list of shot values. - .. code-block:: python + .. code-block:: python - dev = qml.device('default.qubit', wires=1, shots=10) + dev = qml.device('default.qubit', wires=1, shots=10) - @qml.qnode(dev) - def circuit(a): - qml.RX(a, wires=0) - return qml.sample(qml.Z(0)) + @qml.qnode(dev) + def circuit(a): + 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]) - >>> circuit(0.8, shots=[3, 4, 4]) # default is overwritten for this call - (array([1, 1, 1]), array([ 1, -1, 1, 1]), array([1, 1, 1, 1])) - >>> circuit(0.8) # back to default of 10 samples - array([ 1, -1, 1, 1, -1, 1, 1, 1, 1, 1]) + >>> circuit(0.8) # 10 samples are returned + array([ 1, 1, 1, 1, -1, 1, 1, -1, 1, 1]) + >>> circuit(0.8, shots=[3, 4, 4]) # default is overwritten for this call + (array([1, 1, 1]), array([ 1, -1, 1, 1]), array([1, 1, 1, 1])) + >>> circuit(0.8) # back to default of 10 samples + array([ 1, -1, 1, 1, -1, 1, 1, 1, 1, 1]) - When constructing a device, we may optionally pass a dictionary of custom - decompositions to be applied to certain operations upon device execution. - This is useful for enabling support of gates on devices where they would normally - be unsupported. - - For example, suppose we are running on an ion trap device which does not - natively implement the CNOT gate, but we would still like to write our - circuits in terms of CNOTs. On a ion trap device, CNOT can be implemented - using the ``IsingXX`` gate. We first define a decomposition function - (such functions have the signature ``decomposition(*params, wires)``): - - .. code-block:: python - - def ion_trap_cnot(wires, **_): - return [ - qml.RY(np.pi/2, wires=wires[0]), - qml.IsingXX(np.pi/2, wires=wires), - qml.RX(-np.pi/2, wires=wires[0]), - qml.RY(-np.pi/2, wires=wires[0]), - qml.RY(-np.pi/2, wires=wires[1]) - ] - - Next, we create a device, and a QNode for testing. When constructing the - QNode, we can set the expansion strategy to ``"device"`` to ensure the - decomposition is applied and will be viewable when we draw the circuit. - Note that custom decompositions should accept keyword arguments even when - it is not used. - - .. code-block:: python - - # As the CNOT gate normally has no decomposition, we can use default.qubit - # here for expository purposes. - dev = qml.device( - 'default.qubit', wires=2, custom_decomps={"CNOT" : ion_trap_cnot} - ) - - @qml.qnode(dev, expansion_strategy="device") - def run_cnot(): - qml.CNOT(wires=[0, 1]) - return qml.expval(qml.X(1)) - - >>> print(qml.draw(run_cnot)()) - 0: ──RY(1.57)─╭IsingXX(1.57)──RX(-1.57)──RY(-1.57)── - 1: ───────────╰IsingXX(1.57)──RY(-1.57)───────────── - - Some devices may accept additional arguments. For instance, - ``default.gaussian`` accepts the keyword argument ``hbar``, to set - the convention used in the commutation relation :math:`[\x,\p]=i\hbar` - (by default set to 2). + When constructing a device, we may optionally pass a dictionary of custom + decompositions to be applied to certain operations upon device execution. + This is useful for enabling support of gates on devices where they would normally + be unsupported. + + For example, suppose we are running on an ion trap device which does not + natively implement the CNOT gate, but we would still like to write our + circuits in terms of CNOTs. On a ion trap device, CNOT can be implemented + using the ``IsingXX`` gate. We first define a decomposition function + (such functions have the signature ``decomposition(*params, wires)``): + + .. code-block:: python + + def ion_trap_cnot(wires, **_): + return [ + qml.RY(np.pi/2, wires=wires[0]), + qml.IsingXX(np.pi/2, wires=wires), + qml.RX(-np.pi/2, wires=wires[0]), + qml.RY(-np.pi/2, wires=wires[0]), + qml.RY(-np.pi/2, wires=wires[1]) + ] + + Next, we create a device, and a QNode for testing. When constructing the + QNode, we can set the expansion strategy to ``"device"`` to ensure the + decomposition is applied and will be viewable when we draw the circuit. + Note that custom decompositions should accept keyword arguments even when + it is not used. + + .. code-block:: python + + # As the CNOT gate normally has no decomposition, we can use default.qubit + # here for expository purposes. + dev = qml.device( + 'default.qubit', wires=2, custom_decomps={"CNOT" : ion_trap_cnot} + ) + + @qml.qnode(dev, expansion_strategy="device") + def run_cnot(): + qml.CNOT(wires=[0, 1]) + return qml.expval(qml.X(1)) + + >>> print(qml.draw(run_cnot)()) + 0: ──RY(1.57)─╭IsingXX(1.57)──RX(-1.57)──RY(-1.57)── + 1: ───────────╰IsingXX(1.57)──RY(-1.57)───────────── + + Some devices may accept additional arguments. For instance, + ``default.gaussian`` accepts the keyword argument ``hbar``, to set + the convention used in the commutation relation :math:`[\x,\p]=i\hbar` + (by default set to 2). - Please refer to the documentation for the individual devices to see any - additional arguments that might be required or supported. + Please refer to the documentation for the individual devices to see any + additional arguments that might be required or supported. """ if name not in plugin_devices: # Device does not exist in the loaded device list. From 3f4589f8184f22e43715937dbe8d472ce029e5a0 Mon Sep 17 00:00:00 2001 From: Christina Lee Date: Fri, 6 Sep 2024 11:16:38 -0400 Subject: [PATCH 05/11] Update pennylane/devices/device_constructor.py --- pennylane/devices/device_constructor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pennylane/devices/device_constructor.py b/pennylane/devices/device_constructor.py index 4c1468420ce..35f4aa3844d 100644 --- a/pennylane/devices/device_constructor.py +++ b/pennylane/devices/device_constructor.py @@ -127,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='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. From cbdbc191f5c14739d10077d8b0c3303ade192b86 Mon Sep 17 00:00:00 2001 From: Christina Lee Date: Fri, 6 Sep 2024 11:17:18 -0400 Subject: [PATCH 06/11] Apply suggestions from code review --- pennylane/devices/device_constructor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pennylane/devices/device_constructor.py b/pennylane/devices/device_constructor.py index 35f4aa3844d..90312a25fbe 100644 --- a/pennylane/devices/device_constructor.py +++ b/pennylane/devices/device_constructor.py @@ -195,12 +195,12 @@ def ion_trap_cnot(wires, **_): 'default.qubit', wires=2, custom_decomps={"CNOT" : ion_trap_cnot} ) - @qml.qnode(dev, expansion_strategy="device") + @qml.qnode(dev) def run_cnot(): qml.CNOT(wires=[0, 1]) return qml.expval(qml.X(1)) - >>> print(qml.draw(run_cnot)()) + >>> print(qml.draw(run_cnot, level="device")()) 0: ──RY(1.57)─╭IsingXX(1.57)──RX(-1.57)──RY(-1.57)── 1: ───────────╰IsingXX(1.57)──RY(-1.57)───────────── From 30f26735f44773564ade33c20e0864fb19cecfab Mon Sep 17 00:00:00 2001 From: albi3ro Date: Fri, 13 Sep 2024 10:35:58 -0400 Subject: [PATCH 07/11] remove tests --- tests/transforms/test_tape_expand.py | 70 ---------------------------- 1 file changed, 70 deletions(-) diff --git a/tests/transforms/test_tape_expand.py b/tests/transforms/test_tape_expand.py index 3575034d08c..68d2259ed2b 100644 --- a/tests/transforms/test_tape_expand.py +++ b/tests/transforms/test_tape_expand.py @@ -528,30 +528,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 @@ -702,52 +678,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 From 7bf92eed74889f45cb16220d4518cab1f06d5949 Mon Sep 17 00:00:00 2001 From: Christina Lee Date: Fri, 13 Sep 2024 10:36:22 -0400 Subject: [PATCH 08/11] Update doc/releases/changelog-dev.md Co-authored-by: Astral Cai --- doc/releases/changelog-dev.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md index 2e80a745e5d..42d95f62b04 100644 --- a/doc/releases/changelog-dev.md +++ b/doc/releases/changelog-dev.md @@ -40,6 +40,7 @@ [(#6204)](https://github.com/PennyLaneAI/pennylane/pull/6204) * The `decomp_depth` keyword argument to `qml.device` is removed. + [(#6234)](https://github.com/PennyLaneAI/pennylane/pull/6234)

Deprecations πŸ‘‹

From ceb334d3bcb820f329b708ddc972027ba3699b92 Mon Sep 17 00:00:00 2001 From: albi3ro Date: Fri, 13 Sep 2024 11:04:19 -0400 Subject: [PATCH 09/11] remove test --- tests/devices/test_device.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/tests/devices/test_device.py b/tests/devices/test_device.py index c05a5e76309..b5a2a78d945 100644 --- a/tests/devices/test_device.py +++ b/tests/devices/test_device.py @@ -1068,15 +1068,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.""" From 8f6d446ca8cb8241017fad4747d7b8363430cc1f Mon Sep 17 00:00:00 2001 From: Mudit Pandey Date: Tue, 17 Sep 2024 15:08:18 -0400 Subject: [PATCH 10/11] Fix docstring rendering --- pennylane/devices/device_constructor.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pennylane/devices/device_constructor.py b/pennylane/devices/device_constructor.py index 90312a25fbe..1fc4df2acff 100644 --- a/pennylane/devices/device_constructor.py +++ b/pennylane/devices/device_constructor.py @@ -64,28 +64,28 @@ def device(name, *args, **kwargs): PennyLane comes with support for the following devices: * :mod:`'default.qubit' `: a simple - state simulator of qubit-based quantum circuit architectures. + state simulator of qubit-based quantum circuit architectures. * :mod:`'default.mixed' `: a mixed-state - simulator of qubit-based quantum circuit architectures. + simulator of qubit-based quantum circuit architectures. * ``'lightning.qubit'``: a more performant state simulator of qubit-based - quantum circuit architectures written in C++. + quantum circuit architectures written in C++. * :mod:`'default.qutrit' `: a simple - state simulator of qutrit-based quantum circuit architectures. + state simulator of qutrit-based quantum circuit architectures. * :mod:`'default.qutrit.mixed' `: a - mixed-state simulator of qutrit-based quantum circuit architectures. + mixed-state simulator of qutrit-based quantum circuit architectures. * :mod:`'default.gaussian' `: a simple simulator - of Gaussian states and operations on continuous-variable circuit architectures. + of Gaussian states and operations on continuous-variable circuit architectures. * :mod:`'default.clifford' `: an efficient - simulator of Clifford circuits. + simulator of Clifford circuits. * :mod:`'default.tensor' `: a simulator - of quantum circuits based on tensor networks. + of quantum circuits based on tensor networks. Additional devices are supported through plugins β€” see the `available plugins `_ for more From 0319e37b1a245168a67568ffbb73507385090266 Mon Sep 17 00:00:00 2001 From: Mudit Pandey Date: Tue, 17 Sep 2024 15:13:33 -0400 Subject: [PATCH 11/11] [skip ci] Skip CI