Skip to content

Commit

Permalink
Update transforms documentation (#4682)
Browse files Browse the repository at this point in the history
**Description of the Change:**
- `qml.transforms.core.transform` is now top level `qml.transform`
- Update `qml.transforms` page
- Update the documentation for `qml.transforms.core.transform`
- Update thar args and returns of all transform using
`qml.transforms.core.transform`

---------

Co-authored-by: rmoyard <[email protected]>
Co-authored-by: Mudit Pandey <[email protected]>
Co-authored-by: Matthew Silverman <[email protected]>
Co-authored-by: BM7878 <[email protected]>
Co-authored-by: Josh Izaac <[email protected]>
  • Loading branch information
6 people authored Oct 27, 2023
1 parent a9c2ed5 commit c3b6518
Show file tree
Hide file tree
Showing 57 changed files with 1,140 additions and 859 deletions.
58 changes: 35 additions & 23 deletions doc/development/deprecations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,41 @@ Deprecations
Pending deprecations
--------------------

* Passing additional arguments to a transform that decorates a QNode should now be done through use
of ``functools.partial``. For example, the :func:`~pennylane.metric_tensor` transform has an
optional ``approx`` argument which should now be set using:

.. code-block:: python
from functools import partial
@partial(qml.metric_tensor, approx="block-diag")
@qml.qnode(dev)
def circuit(weights):
...
The previously-recommended approach is now deprecated:

.. code-block:: python
@qml.metric_tensor(approx="block-diag")
@qml.qnode(dev)
def circuit(weights):
...
Alternatively, consider calling the transform directly:

.. code-block:: python
@qml.qnode(dev)
def circuit(weights):
...
transformed_circuit = qml.metric_tensor(circuit, approx="block-diag")
- Deprecated in v0.33
- Will be removed in v0.35

* ``qml.ExpvalCost`` has been deprecated, and usage will now raise a warning.

- Deprecated in v0.24
Expand Down Expand Up @@ -155,29 +190,6 @@ Completed deprecation cycles
- Deprecated in v0.32
- Removed in v0.33

* The following decorator syntax for transforms has been deprecated:

.. code-block:: python
@transform_fn(**transform_kwargs)
@qml.qnode(dev)
def circuit():
...
If you are using a transform that has supporting ``transform_kwargs``, please call the
transform directly using ``circuit = transform_fn(circuit, **transform_kwargs)``,
or use ``functools.partial``:

.. code-block:: python
@functools.partial(transform_fn, **transform_kwargs)
@qml.qnode(dev)
def circuit():
...
- Deprecated in v0.33
- Will be removed in v0.34

* The ``mode`` keyword argument in ``QNode`` has been removed, as it was only used in the old return
system (which has also been removed). Please use ``grad_on_execution`` instead.

Expand Down
8 changes: 4 additions & 4 deletions doc/introduction/compiling_circuits.rst
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,9 @@ For example, take the following decorated quantum function:
dev = qml.device('default.qubit', wires=[0, 1, 2])
@qml.compile
@qml.qnode(dev)
@qml.compile()
def qfunc(x, y, z):
def circuit(x, y, z):
qml.Hadamard(wires=0)
qml.Hadamard(wires=1)
qml.Hadamard(wires=2)
Expand All @@ -157,7 +157,7 @@ The default behaviour of :func:`~.pennylane.compile` applies a sequence of three
transforms: :func:`~.pennylane.transforms.commute_controlled`, :func:`~.pennylane.transforms.cancel_inverses`,
and then :func:`~.pennylane.transforms.merge_rotations`.

>>> print(qml.draw(qfunc)(0.2, 0.3, 0.4))
>>> print(qml.draw(circuit)(0.2, 0.3, 0.4))
0: ──H──RX(0.60)─────────────────┤ <Z>
1: ──H─╭X─────────────────────╭●─┤
2: ──H─╰●─────────RX(0.30)──Y─╰Z─┤
Expand All @@ -173,8 +173,8 @@ controlled gates and cancel adjacent inverses, we could do:
from pennylane.transforms import commute_controlled, cancel_inverses
pipeline = [commute_controlled, cancel_inverses]
@partial(qml.compile, pipeline=pipeline)
@qml.qnode(dev)
@qml.compile(pipeline=pipeline)
def qfunc(x, y, z):
qml.Hadamard(wires=0)
qml.Hadamard(wires=1)
Expand Down
1 change: 1 addition & 0 deletions pennylane/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
from pennylane import qaoa
from pennylane.qnode import QNode, qnode
from pennylane.transforms import (
transform,
adjoint_metric_tensor,
batch_params,
batch_input,
Expand Down
2 changes: 1 addition & 1 deletion pennylane/devices/device_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ def preprocess(
**Example**
All the transforms that are part of the preprocessing need to respect the transform contract defined in
:func:`pennylane.transforms.core.transform`.
:func:`pennylane.transform`.
.. code-block:: python
Expand Down
63 changes: 30 additions & 33 deletions pennylane/devices/preprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
)
from pennylane.typing import ResultBatch, Result
from pennylane import DeviceError
from pennylane.transforms.core import transform
from pennylane import transform
from pennylane.wires import WireError

PostprocessingFn = Callable[[ResultBatch], Union[Result, ResultBatch]]
Expand Down Expand Up @@ -87,8 +87,14 @@ def no_sampling(
"""Raises an error if the tape has finite shots.
Args:
tape (QuantumTape): a quantum circuit
name="device" (str): name to use in error message.
tape (QuantumTape or .QNode or Callable): a quantum circuit
name (str): name to use in error message.
Returns:
qnode (QNode) or quantum function (Callable) or tuple[List[.QuantumTape], function]:
The unaltered input circuit. The output type is explained in :func:`qml.transform <pennylane.transform>`.
This transform can be added to forbid finite shots. For example, ``default.qubit`` uses it for
adjoint and backprop validation.
Expand All @@ -107,17 +113,15 @@ def validate_device_wires(
across all available wires.
Args:
tape (QuantumTape): a quantum circuit.
tape (QuantumTape or QNode or Callable): a quantum circuit.
wires=None (Optional[Wires]): the allowed wires. Wires of ``None`` allows any wires
to be present in the tape.
name="device" (str): the name of the device to use in error messages.
Returns:
pennylane.QNode or qfunc or Tuple[List[.QuantumTape], Callable]: If a QNode is passed,
it returns a QNode with the transform added to its transform program.
If a tape is passed, returns a tuple containing a list of
quantum tapes to be evaluated, and a function to be applied to these
tape executions.
qnode (QNode) or quantum function (Callable) or tuple[List[QuantumTape], function]:
The unaltered input circuit. The output type is explained in :func:`qml.transform <pennylane.transform>`.
Raises:
WireError: if the tape has a wire not present in the provided wires.
Expand Down Expand Up @@ -153,16 +157,15 @@ def validate_multiprocessing_workers(
threads per worker.
Args:
tape (QuantumTape): a quantum circuit.
tape (QuantumTape or .QNode or Callable): a quantum circuit.
max_workers (int): Maximal number of multiprocessing workers
device (pennylane.devices.Device): The device to be checked.
Returns:
pennylane.QNode or qfunc or Tuple[List[.QuantumTape], Callable]: If a QNode is passed,
it returns a QNode with the transform added to its transform program.
If a tape is passed, returns a tuple containing a list of
quantum tapes to be evaluated, and a function to be applied to these
tape executions.
qnode (pennylane.QNode) or quantum function (callable) or tuple[List[.QuantumTape], function]:
The unaltered input circuit. The output type is explained in :func:`qml.transform <pennylane.transform>`.
"""
if max_workers is not None:
threads_per_proc = os.cpu_count() # all threads by default
Expand Down Expand Up @@ -238,7 +241,7 @@ def decompose(
"""Decompose operations until the stopping condition is met.
Args:
tape (QuantumTape): a quantum circuit.
tape (QuantumTape or QNode or Callable): a quantum circuit.
stopping_condition (Callable): a function from an operator to a boolean. If ``False``, the operator
should be decomposed. If an operator cannot be decomposed and is not accepted by ``stopping_condition``,
a ``DecompositionUndefinedError`` will be raised.
Expand All @@ -249,11 +252,9 @@ def decompose(
Returns:
pennylane.QNode or qfunc or Tuple[List[.QuantumTape], Callable]: If a QNode is passed,
it returns a QNode with the transform added to its transform program.
If a tape is passed, returns a tuple containing a list of
quantum tapes to be evaluated, and a function to be applied to these
tape executions.
qnode (QNode) or quantum function (Callable) or tuple[List[QuantumTape], function]:
The decomposed circuit. The output type is explained in :func:`qml.transform <pennylane.transform>`.
Raises:
DecompositionUndefinedError: if an operator is not accepted and does not define a decomposition
Expand Down Expand Up @@ -339,16 +340,14 @@ def validate_observables(
"""Validates the observables and measurements for a circuit.
Args:
tape (QuantumTape): a quantum circuit.
tape (QuantumTape or QNode or Callable): a quantum circuit.
stopping_condition (callable): a function that specifies whether or not an observable is accepted.
name (str): the name of the device to use in error messages.
Returns:
pennylane.QNode or qfunc or Tuple[List[.QuantumTape], Callable]: If a QNode is passed,
it returns a QNode with the transform added to its transform program.
If a tape is passed, returns a tuple containing a list of
quantum tapes to be evaluated, and a function to be applied to these
tape executions.
qnode (QNode) or quantum function (Callable) or tuple[List[.QuantumTape], function]:
The unaltered input circuit. The output type is explained in :func:`qml.transform <pennylane.transform>`.
Raises:
DeviceError: if an observable is not supported
Expand Down Expand Up @@ -383,19 +382,17 @@ def validate_measurements(
"""Validates the supported state and sample based measurement processes.
Args:
tape (QuantumTape): a quantum circuit.
tape (QuantumTape, .QNode, Callable): a quantum circuit.
analytic_measurements (Callable[[MeasurementProcess], bool]): a function from a measurement process
to whether or not it is accepted in analytic simulations.
sample_measurements (Callable[[MeasurementProcess], bool]): a function from a measurement process
to whether or not it accepted for finite shot siutations
name (str): the name to use in error messages.
Returns:
pennylane.QNode or qfunc or Tuple[List[.QuantumTape], Callable]: If a QNode is passed,
it returns a QNode with the transform added to its transform program.
If a tape is passed, returns a tuple containing a list of
quantum tapes to be evaluated, and a function to be applied to these
tape executions.
qnode (pennylane.QNode) or quantum function (callable) or tuple[List[.QuantumTape], function]:
The unaltered input circuit. The output type is explained in :func:`qml.transform <pennylane.transform>`.
Raises:
DeviceError: if a measurement process is not supported.
Expand Down
11 changes: 7 additions & 4 deletions pennylane/fourier/circuit_spectrum.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
preprocessing in the QNode."""
from typing import Sequence, Callable
from functools import partial
from pennylane.transforms.core import transform
from pennylane import transform
from pennylane.tape import QuantumTape
from .utils import get_spectrum, join_spectra

Expand Down Expand Up @@ -48,15 +48,17 @@ def circuit_spectrum(
If no input-encoding gates are found, an empty dictionary is returned.
Args:
tape (QuantumTape): a quantum node representing a circuit in which
tape (QNode or QuantumTape or Callable): a quantum circuit in which
input-encoding gates are marked by their ``id`` attribute
encoding_gates (list[str]): list of input-encoding gate ``id`` strings
for which to compute the frequency spectra
decimals (int): number of decimals to which to round frequencies.
Returns:
(dict[str, list[float]]): Dictionary with the input-encoding gate ``id`` as keys and
their frequency spectra as values.
qnode (QNode) or quantum function (Callable) or tuple[List[QuantumTape], function]:
The transformed circuit as described in :func:`qml.transform <pennylane.transform>`. Executing this circuit
will return a dictionary with the input-encoding gate ``id`` as keys and their frequency spectra as values.
**Details**
Expand Down Expand Up @@ -185,6 +187,7 @@ def circuit(x):
"""

def processing_fn(tapes):
"""Process the tapes extract the spectrum of the circuit."""
tape = tapes[0]
freqs = {}
for op in tape.operations:
Expand Down
22 changes: 8 additions & 14 deletions pennylane/gradients/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,6 @@
stoch_pulse_grad
pulse_odegen
Custom gradients
^^^^^^^^^^^^^^^^
.. autosummary::
:toctree: api
gradient_transform
hessian_transform
Utility functions
^^^^^^^^^^^^^^^^^
Expand Down Expand Up @@ -131,7 +122,10 @@ def circuit(weights):
Transforming QNodes
-------------------
Alternatively, quantum gradient transforms can be applied manually to QNodes.
Alternatively, quantum gradient transforms can be applied manually to QNodes. This is not
recommended because PennyLane must compute the classical Jacobian of the parameters and multiply it with
the quantum Jacobian, we recommend using the ``diff_method`` kwargs with your favorite machine learning
framework.
.. code-block:: python
Expand Down Expand Up @@ -301,21 +295,21 @@ def circuit(weights):
Custom gradient transforms
--------------------------
Using the :class:`~.gradient_transform` decorator, custom gradient transforms
Using the :func:`qml.transform <pennylane.transform>` decorator, custom gradient transforms
can be created:
.. code-block:: python
@gradient_transform
def my_custom_gradient(tape, **kwargs):
@transform
def my_custom_gradient(tape: qml.tape.QuantumTape, **kwargs) -> (Sequence[qml.tape.QuantumTape], Callable):
...
return gradient_tapes, processing_fn
Once created, a custom gradient transform can be applied directly
to QNodes, or registered as the quantum gradient transform to use
during autodifferentiation.
For more details, please see the :class:`~.gradient_transform`
For more details, please see the :func:`qml.transform <pennylane.transform>`
documentation.
"""
import pennylane as qml
Expand Down
Loading

0 comments on commit c3b6518

Please sign in to comment.