From be144a49524bc3a0f3f0e62f446f99697c8b2082 Mon Sep 17 00:00:00 2001 From: albi3ro Date: Fri, 19 Jan 2024 17:23:21 -0500 Subject: [PATCH 01/19] add construct_batch and transform_program functions to workflow module --- doc/releases/changelog-dev.md | 5 + pennylane/_qubit_device.py | 3 +- pennylane/devices/default_qubit.py | 18 +- pennylane/transforms/core/__init__.py | 2 +- pennylane/transforms/core/transform.py | 47 +++- .../transforms/core/transform_dispatcher.py | 3 + .../transforms/core/transform_program.py | 46 +++- pennylane/workflow/__init__.py | 3 + pennylane/workflow/construct_batch.py | 233 ++++++++++++++++++ pennylane/workflow/qnode.py | 47 ++-- .../test_transform_dispatcher.py | 152 +++++++----- .../test_transform_program.py | 35 +++ tests/workflow/test_construct_batch.py | 125 ++++++++++ 13 files changed, 621 insertions(+), 98 deletions(-) create mode 100644 pennylane/workflow/construct_batch.py create mode 100644 tests/workflow/test_construct_batch.py diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md index 3ddd156b4d6..1d8a1df33b4 100644 --- a/doc/releases/changelog-dev.md +++ b/doc/releases/changelog-dev.md @@ -54,6 +54,11 @@ * Raise a more informative error when calling `adjoint_jacobian` with trainable state-prep operations. [(#5026)](https://github.com/PennyLaneAI/pennylane/pull/5026) +* Adds `qml.workflow.transform_program` and `qml.workflow.construct_batch` to inspect the transform program and batch of tapes + at different stages. + +* Adds a `qml.transforms.core.expand_fn_transform` that converts a tape-> tape function into a transform. +

Community contributions 🥳

* The transform `split_non_commuting` now accepts measurements of type `probs`, `sample` and `counts` which accept both wires and observables. diff --git a/pennylane/_qubit_device.py b/pennylane/_qubit_device.py index c8a515c320f..405cd34bee8 100644 --- a/pennylane/_qubit_device.py +++ b/pennylane/_qubit_device.py @@ -32,7 +32,6 @@ import pennylane as qml from pennylane import Device, DeviceError -from pennylane.workflow import set_shots from pennylane.math import multiply as qmlmul from pennylane.math import sum as qmlsum from pennylane.measurements import ( @@ -1036,7 +1035,7 @@ def classical_shadow(self, obs, circuit): n_snapshots = self.shots seed = obs.seed - with set_shots(self, shots=1): + with qml.workflow.set_shots(self, shots=1): # slow implementation but works for all devices n_qubits = len(wires) mapped_wires = np.array(self.map_wires(wires)) diff --git a/pennylane/devices/default_qubit.py b/pennylane/devices/default_qubit.py index 4f3d5451863..e82acf69bcf 100644 --- a/pennylane/devices/default_qubit.py +++ b/pennylane/devices/default_qubit.py @@ -159,6 +159,16 @@ def adjoint_state_measurements( ) +def adjoint_ops(op: qml.operation.Operator) -> bool: + """Specify whether or not an Operator is supported by adjoint differentiation.""" + return op.num_params == 0 or op.num_params == 1 and op.has_generator + + +def adjoint_observables(obs: qml.operation.Operator) -> bool: + """Specifies whether or not an observable is compatible with adjoint differentiation on DefaultQubit.""" + return obs.has_matrix + + def _add_adjoint_transforms(program: TransformProgram, device_vjp=False) -> None: """Private helper function for ``preprocess`` that adds the transforms specific for adjoint differentiation. @@ -171,14 +181,6 @@ def _add_adjoint_transforms(program: TransformProgram, device_vjp=False) -> None """ - def adjoint_ops(op: qml.operation.Operator) -> bool: - """Specify whether or not an Operator is supported by adjoint differentiation.""" - return op.num_params == 0 or op.num_params == 1 and op.has_generator - - def adjoint_observables(obs: qml.operation.Operator) -> bool: - """Specifies whether or not an observable is compatible with adjoint differentiation on DefaultQubit.""" - return obs.has_matrix - name = "adjoint + default.qubit" program.add_transform(no_sampling, name=name) program.add_transform( diff --git a/pennylane/transforms/core/__init__.py b/pennylane/transforms/core/__init__.py index ff2b97cc900..bcddcbf5d98 100644 --- a/pennylane/transforms/core/__init__.py +++ b/pennylane/transforms/core/__init__.py @@ -14,6 +14,6 @@ r"""This module contains the experimental transforms building blocks (core). """ -from .transform import transform +from .transform import transform, expand_fn_transform from .transform_dispatcher import TransformDispatcher, TransformContainer, TransformError from .transform_program import TransformProgram diff --git a/pennylane/transforms/core/transform.py b/pennylane/transforms/core/transform.py index acbd57931f3..72d394b356d 100644 --- a/pennylane/transforms/core/transform.py +++ b/pennylane/transforms/core/transform.py @@ -15,7 +15,8 @@ This module contains the transform function/decorator to make your custom transforms compatible with tapes, quantum functions and QNodes. """ -from typing import get_type_hints +from functools import wraps +from typing import get_type_hints, Callable from .transform_dispatcher import TransformDispatcher, TransformError @@ -23,7 +24,7 @@ def transform( quantum_transform, expand_transform=None, classical_cotransform=None, - is_informative=None, + is_informative=False, final_transform=False, ): """Generalizes a function that transforms tapes to work with additional circuit-like objects such as a @@ -50,7 +51,7 @@ def transform( ``quantum_transform``. classical_cotransform (Callable): A classical co-transform is a function to post-process the classical jacobian and the quantum jacobian and has the signature: ``my_cotransform(qjac, cjac, tape) -> tensor_like`` - is_informative (bool): Whether or not a transform is informative. If true the transform is queued at the end + is_informative=False (bool): Whether or not a transform is informative. If true the transform is queued at the end of the transform program and the tapes or qnode aren't executed. final_transform (bool): Whether or not the transform is terminal. If true the transform is queued at the end of the transform program. ``is_informative`` supersedes ``final_transform``. @@ -177,15 +178,45 @@ def qnode_circuit(a): ) # 3: CHeck the classical co-transform - if classical_cotransform is not None: - if not callable(classical_cotransform): - raise TransformError("The classical co-transform must be a valid Python function.") + if classical_cotransform is not None and not callable(classical_cotransform): + raise TransformError("The classical co-transform must be a valid Python function.") - dispatcher = TransformDispatcher( + return TransformDispatcher( quantum_transform, expand_transform=expand_transform, classical_cotransform=classical_cotransform, is_informative=is_informative, final_transform=final_transform, ) - return dispatcher + + +def null_postprocessing(results): + """A postprocessing function with null behavior.""" + return results[0] + + +def expand_fn_transform( + expand_fn: Callable[["pennylane.tape.QuantumTape"], "pennylane.tape.QuantumTape"] +) -> "TransformDispatcher": + """Construct a transform from a tape-> tape function. + + Args: + expand_fn (Callable): a function from a single tape to a single tape + + Returns: + + .TransformDispatcher: Returns a transform dispatcher object that that can transform any + circuit-like object in PennyLane. + + >>> device = qml.device('default.qubit.legacy', wires=2) + >>> my_transform = qml.transforms.core.expand_fn_transform(device.expand_fn) + >>> my_transform + + + """ + + @wraps(expand_fn) + def wrapped_expand_fn(tape): + return (expand_fn(tape),), null_postprocessing + + return transform(wrapped_expand_fn) diff --git a/pennylane/transforms/core/transform_dispatcher.py b/pennylane/transforms/core/transform_dispatcher.py index 147fddce7e8..99a80098c5e 100644 --- a/pennylane/transforms/core/transform_dispatcher.py +++ b/pennylane/transforms/core/transform_dispatcher.py @@ -343,6 +343,9 @@ def __init__( self._is_informative = is_informative self._final_transform = is_informative or final_transform + def __repr__(self): + return f"<{self._transform.__name__}({self._args}, {self._kwargs})>" + def __iter__(self): return iter( ( diff --git a/pennylane/transforms/core/transform_program.py b/pennylane/transforms/core/transform_program.py index ba175e91d53..9f288eb4314 100644 --- a/pennylane/transforms/core/transform_program.py +++ b/pennylane/transforms/core/transform_program.py @@ -15,7 +15,7 @@ This module contains the ``TransformProgram`` class. """ from functools import partial -from typing import Callable, List, Tuple, Optional, Sequence +from typing import Callable, List, Tuple, Optional, Sequence, Union import pennylane as qml from pennylane.typing import Result, ResultBatch @@ -117,6 +117,35 @@ class TransformProgram: .. seealso:: :func:`~.pennylane.transform` + **Implemented Dunder methods** + + Programs have several implemented dunder methods for easy manipulation. + + >>> program = TransformProgram() + >>> program.add_transform(qml.compile) + >>> program.add_transform(qml.transforms.cancel_inverses) + >>> [t for t in program] # Iteration + [, ] + >>> program[0] + + >>> program[::-1] + TransformProgram(cancel_inverses, compile) + >>> len(program) + 2 + >>> True if program else False + True + >>> True if TransformProgram() else False + False + >>> program2 = copy.copy(program) + >>> program2 == program + True + >>> qml.compile in program + True + >>> qml.transforms.hamiltonian_expand in program + False + >>> program + program + TransformProgram(compile, cancel_inverses, compile, cancel_inverses) + """ def __init__(self, initial_program: Optional[Sequence] = None): @@ -132,9 +161,11 @@ def __len__(self): """int: Return the number transforms in the program.""" return len(self._transform_program) - def __getitem__(self, idx): + def __getitem__(self, idx) -> Union["TransformProgram", "TransformContainer"]: """(TransformContainer, List[TransformContainer]): Return the indexed transform container from underlying transform program""" + if isinstance(idx, slice): + return TransformProgram(self._transform_program[idx]) return self._transform_program[idx] def __bool__(self): @@ -155,12 +186,19 @@ def __repr__(self): contents = ", ".join(f"{transform_c.transform.__name__}" for transform_c in self) return f"TransformProgram({contents})" - def __eq__(self, other): + def __eq__(self, other) -> bool: if not isinstance(other, TransformProgram): return False return self._transform_program == other._transform_program + def __contains__(self, obj): + if isinstance(obj, TransformContainer): + return obj in self._transform_program + if isinstance(obj, TransformDispatcher): + return any(obj.transform == t.transform for t in self) + raise ValueError(f"Contains not implemented for TransformProgram and object {obj}") + def push_back(self, transform_container: TransformContainer): """Add a transform (container) to the end of the program. @@ -290,7 +328,7 @@ def is_informative(self) -> bool: @property def has_final_transform(self) -> bool: """``True`` if the transform program has a terminal transform.""" - return self[-1].final_transform if self else False + return self[-1].final_transform if self else False # pylint: disable=no-member def has_classical_cotransform(self) -> bool: """Check if the transform program has some classical cotransforms. diff --git a/pennylane/workflow/__init__.py b/pennylane/workflow/__init__.py index 231206b6182..eb7a66f3581 100644 --- a/pennylane/workflow/__init__.py +++ b/pennylane/workflow/__init__.py @@ -25,6 +25,8 @@ ~execute ~workflow.cache_execute ~workflow.set_shots + ~workflow.construct_batch + ~workflow.transform_program Supported interfaces ~~~~~~~~~~~~~~~~~~~~ @@ -55,3 +57,4 @@ from .set_shots import set_shots from .execution import execute, cache_execute, SUPPORTED_INTERFACES, INTERFACE_MAP from .qnode import QNode, qnode +from .construct_batch import construct_batch, transform_program diff --git a/pennylane/workflow/construct_batch.py b/pennylane/workflow/construct_batch.py new file mode 100644 index 00000000000..ba4d71fbc8b --- /dev/null +++ b/pennylane/workflow/construct_batch.py @@ -0,0 +1,233 @@ +# Copyright 2018-2024 Xanadu Quantum Technologies Inc. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Contains a function extracting the tapes at postprocessing at any stage of a transform program. + +""" +from typing import Union, Callable, Tuple + +import pennylane as qml +from .qnode import QNode, _make_execution_config, _get_device_shots + + +def _get_full_transform_program(qnode: QNode) -> "qml.transforms.core.TransformProgram": + program = qml.transforms.core.TransformProgram(qnode.transform_program) + if getattr(qnode.gradient_fn, "expand_transform", False): + program.add_transform( + qml.transform(qnode.gradient_fn.expand_transform), + **qnode.gradient_kwargs, + ) + if isinstance(qnode.device, qml.devices.Device): + config = _make_execution_config(qnode) + return program + qnode.device.preprocess(config)[0] + program.add_transform(qml.transform(qnode.device.batch_transform)) + program.add_transform(qml.transforms.core.expand_fn_transform(qnode.device.expand_fn)) + return program + + +def transform_program(qnode: "QNode", level=None) -> "qml.transforms.core.TransformProgram": + """Extract a transform program at a designated level. + + Args: + qnode (QNode): ? + level (None, str, int, slice): And indication + + * ``None``: use the full transform program + * ``str``: Acceptable keys are ``"user"``, ``"device"``, and ``"gradient"`` + * ``int``: How many transforms to include, starting from the front of the program + * ``slice``: a slice to select out components of the transform program. + + Returns: + TransformProrgram: the transform program corresponding to t + + + .. code-block:: python + + dev = qml.device('default.qubit', wires=4) + + @qml.transforms.merge_rotations + @qml.transforms.cancel_inverses + @qml.qnode(dev, diff_method="parameter-shift", shifts=np.pi / 4) + def circuit(): + return qml.expval(qml.PauliZ(0)) + + By default, we get the full transform program: + + >>> qml.workflow.transform_program(circuit) + TransformProgram(cancel_inverses, merge_rotations, _expand_transform_param_shift, + validate_device_wires, defer_measurements, decompose, validate_measurements, + validate_observables) + + The `"user"` transforms are the one's manually applied to the qnode, :class:`~.cancel_inverses` and + :class:`~.merge_rotations`. + + >>> qml.workflow.transform_program(circuit, level="user") + TransformProgram(cancel_inverses, merge_rotations) + + The ``_expand_transform_param_shift`` is the ``"gradient"`` transform. This expands all trainable + operations to a state where the parameter shift transform can operate on them. For example, it will decompose + any parametrized templates into operators that have generators. + + >>> qml.workflow.transform_program(circuit, level="gradient") + TransformProgram(cancel_inverses, merge_rotations, _expand_transform_param_shift) + + ``"device"`` includes all transforms in the full transform program. This corresponds to the circuits that will + be sent to the device to execute. + + >>> qml.workflow.transform_program(circuit, level="device") + TransformProgram(cancel_inverses, merge_rotations, _expand_transform_param_shift, + validate_device_wires, defer_measurements, decompose, validate_measurements, + validate_observables) + + >>> qml.workflow.transform_program(circuit, level="top") + TransformProgram() + + >>> qml.workflow.transform_program(circuit, level=2) + TransformProgram(cancel_inverses, merge_rotations) + + ``level`` can also accept a ``slice`` object to select out any arbitrary subset of the transform program. This allows you to select + different starting transforms or strides. Fro example, you can get the transform program with a reversed order. + + >>> qml.workflow.transform_program(circuit, level=slice(1,3)) + TransformProgram(merge_rotations, _expand_transform_param_shift) + >>> qml.workflow.transform_program(circuit, level=slice(None, 0, -1)) + TransformProgram(validate_observables, validate_measurements, decompose, + defer_measurements, validate_device_wires, _expand_transform_param_shift, merge_rotations) + + + """ + full_transform_program = _get_full_transform_program(qnode) + + if level == "device": + level = None + elif level == "top": + level = 0 + elif level == "user": + level = len(qnode.transform_program) + elif level == "gradient": + if getattr(qnode.gradient_fn, "expand_transform", False): + level = slice(0, len(qnode.transform_program) + 1) + else: + level = slice(0, len(qnode.transform_program)) + + if level is None or isinstance(level, int): + level = slice(0, level) + return full_transform_program[level] + + +def construct_batch(qnode: QNode, level: Union[None, str, int, slice] = "user") -> Callable: + """Construct the batch of tapes and post processing for a designated stage in the transform program. + + Args: + qnode (QNode): ? not sure how to best define qnode here ? + level (None, str, int, slice): And indication + + * ``None``: use the full transform program + * ``str``: Acceptable keys are ``"user"``, ``"device"``, and ``"gradient"`` + * ``int``: How many transforms to include, starting from the front of the program + * ``slice``: a slice to select out components of the transform program. + + Returns: + Callable: a function with the same call signature as the initial quantum function. This function returns + a batch (tuple) of tapes and postprocessing function. + + Suppose we have a device with several user transforms. + + .. code-block:: python + + x = np.array([0.1, 0.2]) + + dev = qml.device('default.qubit', wires=4) + + @qml.transforms.merge_rotations + @qml.transforms.cancel_inverses + @qml.qnode(dev, diff_method="parameter-shift", shifts=np.pi / 4) + def circuit(): + return qml.expval(qml.PauliZ(0)) + + We can inspect what the device will execute with: + + >>> batch, fn = construct_batch(circuit, expansion_strategy="device")(1.23) + >>> batch[0].circuit + [SWAP(wires=[0, 2]), + SWAP(wires=[1, 2]), + RY(tensor(1., requires_grad=True), wires=[0]), + RX(tensor(2., requires_grad=True), wires=[1]), + expval(PauliX(wires=[0]) + PauliY(wires=[0]))] + + These tapes can be natively executed by the device, though with non-backprop devices the parameters + will need to be converted to numpy with :func:`~.convert_to_numpy_parameters`. + + >>> fn(dev.execute(batch)) + (tensor(0.84147098, requires_grad=True),) + + Or what the parameter shift gradient transform will be applied to: + + >>> batch, fn = construct_batch(circuit, xpansion_strategy="gradient")(1.23) + >>> batch[0].circuit + [Permute(wires=[0, 1, 2]), + RY(tensor(1., requires_grad=True), wires=[0]), + RX(tensor(2., requires_grad=True), wires=[1]), + expval(PauliX(wires=[0]) + PauliY(wires=[0]))] + + We can inpsect what was directly captured from the qfunc with ``expansion_strategy=0``. + + >>> batch, fn = construct_batch(circuit, expansion_strategy=0)(1.23) + >>> batch[0].circuit + [Permute(wires=[0, 1, 2]), + RandomLayers(tensor([[1., 2.]], requires_grad=True), wires=[0, 1]), + RX(1.23, wires=[0]), + RX(-1.23, wires=[0]), + PauliX(wires=[0]), + PauliX(wires=[0]), + expval(PauliX(wires=[0]) + PauliY(wires=[0]))] + + And iterate though stages in the transform program with different integers. + If we request ``expansion_strategy=1``, the ``cancel_inverses`` transform has been applied. + + >>> batch, fn = construct_batch(circuit, expansion_strategy=1)(1.23) + >>> batch[0].circuit + [Permute(wires=[0, 1, 2]), + RandomLayers(tensor([[1., 2.]], requires_grad=True), wires=[0, 1]), + RX(1.23, wires=[0]), + RX(-1.23, wires=[0]), + expval(PauliX(wires=[0]) + PauliY(wires=[0]))] + + We can also slice into a subset of the transform program. ``slice(1, None)`` would skip the first user + transform ``cancel_inverses``: + + >>> batch, fn = construct_batch(circuit, expansion_strategy=slice(1,None))(1.23, include_permute=False) + >>> batch[0].circuit + [RY(tensor(1., requires_grad=True), wires=[0]), + RX(tensor(2., requires_grad=True), wires=[1]), + PauliX(wires=[0]), + PauliX(wires=[0]), + expval(PauliX(wires=[0]) + PauliY(wires=[0]))] + + """ + program = transform_program(qnode, level=level) + + def batch_constructor(*args, **kwargs) -> Tuple[Tuple["qml.tape.QuantumTape", Callable]]: + """Create a batch of tapes and a post processing function.""" + if qnode.qfunc_uses_shots_arg: + shots = _get_device_shots(qnode.device) + else: + shots = kwargs.pop("shots", _get_device_shots(qnode.device)) + + with qml.queuing.AnnotatedQueue() as q: + qnode.func(*args, **kwargs) + + initial_tape = qml.tape.QuantumScript.from_queue(q, shots) + return program((initial_tape,)) + + return batch_constructor diff --git a/pennylane/workflow/qnode.py b/pennylane/workflow/qnode.py index 8a37364547f..149433082ec 100644 --- a/pennylane/workflow/qnode.py +++ b/pennylane/workflow/qnode.py @@ -62,6 +62,26 @@ def _get_device_shots(device) -> Shots: return device.shots +def _make_execution_config(circuit: "QNode") -> "qml.devices.ExecutionConfig": + if circuit.gradient_fn is None: + _gradient_method = None + elif isinstance(circuit.gradient_fn, str): + _gradient_method = circuit.gradient_fn + else: + _gradient_method = "gradient-transform" + grad_on_execution = circuit.execute_kwargs.get("grad_on_execution") + if circuit.interface == "jax": + grad_on_execution = False + elif grad_on_execution == "best": + grad_on_execution = None + return qml.devices.ExecutionConfig( + interface=circuit.interface, + gradient_method=_gradient_method, + grad_on_execution=grad_on_execution, + use_device_jacobian_product=circuit.execute_kwargs["device_vjp"], + ) + + class QNode: """Represents a quantum node in the hybrid computational graph. @@ -514,6 +534,14 @@ def __repr__(self): self.diff_method, ) + @property + def qfunc_uses_shots_arg(self) -> bool: + """Whether or not the qfunc has a ``shots`` keyword argument. + + If so, shots cannot be dynamically set on a call to a ``QNode``. + """ + return self._qfunc_uses_shots_arg + @property def interface(self): """The interface used by the QNode""" @@ -988,24 +1016,7 @@ def __call__(self, *args, **kwargs) -> qml.typing.Result: config = None # Add the device program to the QNode program if isinstance(self.device, qml.devices.Device): - if self.gradient_fn is None: - _gradient_method = None - elif isinstance(self.gradient_fn, str): - _gradient_method = self.gradient_fn - else: - _gradient_method = "gradient-transform" - grad_on_execution = self.execute_kwargs.get("grad_on_execution") - if self.interface == "jax": - grad_on_execution = False - elif grad_on_execution == "best": - grad_on_execution = None - - config = qml.devices.ExecutionConfig( - interface=self.interface, - gradient_method=_gradient_method, - grad_on_execution=grad_on_execution, - use_device_jacobian_product=self.execute_kwargs["device_vjp"], - ) + config = _make_execution_config(self) device_transform_program, config = self.device.preprocess(execution_config=config) full_transform_program = self.transform_program + device_transform_program else: diff --git a/tests/transforms/test_experimental/test_transform_dispatcher.py b/tests/transforms/test_experimental/test_transform_dispatcher.py index b7a5160bb52..7e103d57864 100644 --- a/tests/transforms/test_experimental/test_transform_dispatcher.py +++ b/tests/transforms/test_experimental/test_transform_dispatcher.py @@ -18,6 +18,7 @@ import pytest import pennylane as qml from pennylane.transforms.core import transform, TransformError, TransformContainer +from pennylane.transforms.core.transform_dispatcher import TransformDispatcher dev = qml.device("default.qubit", wires=2) @@ -150,6 +151,73 @@ def fn(results): return [tape], fn +class TestTransformContainer: + """Tests for the TransformContainer dataclass.""" + + def test_repr(self): + """Tests for the repr of a transform container.""" + t1 = qml.transforms.core.TransformContainer( + qml.transforms.compile.transform, kwargs={"num_passes": 2, "expand_depth": 1} + ) + assert repr(t1) == "" + + def test_equality(self): + """Tests that we can compare TransformContainer objects with the '==' and '!=' operators.""" + + t1 = TransformContainer( + qml.transforms.compile.transform, kwargs={"num_passes": 2, "expand_depth": 1} + ) + t2 = TransformContainer( + qml.transforms.compile.transform, kwargs={"num_passes": 2, "expand_depth": 1} + ) + t3 = TransformContainer( + qml.transforms.transpile.transform, kwargs={"coupling_map": [(0, 1), (1, 2)]} + ) + t4 = TransformContainer( + qml.transforms.compile.transform, kwargs={"num_passes": 2, "expand_depth": 2} + ) + + t5 = TransformContainer(qml.transforms.merge_rotations.transform, args=(1e-6,)) + t6 = TransformContainer(qml.transforms.merge_rotations.transform, args=(1e-7,)) + + # test for equality of identical transformers + assert t1 == t2 + + # test for inequality of different transformers + assert t1 != t3 + assert t2 != t3 + assert t1 != 2 + assert t1 != t4 + assert t5 != t6 + assert t5 != t1 + + # Test equality with the same args + t5_copy = TransformContainer(qml.transforms.merge_rotations.transform, args=(1e-6,)) + assert t5 == t5_copy + + def test_the_transform_container_attributes(self): + """Test the transform container attributes.""" + container = qml.transforms.core.TransformContainer( + first_valid_transform, args=[0], kwargs={}, classical_cotransform=None + ) + + q_transform, args, kwargs, cotransform, is_informative, final_transform = container + + assert q_transform is first_valid_transform + assert args == [0] + assert kwargs == {} + assert cotransform is None + assert not is_informative + assert not final_transform + + assert container.transform is first_valid_transform + assert container.args == [0] + assert not container.kwargs + assert container.classical_cotransform is None + assert not container.is_informative + assert not container.final_transform + + class TestTransformDispatcher: # pylint: disable=too-many-public-methods """Test the transform function (validate and dispatch).""" @@ -194,7 +262,7 @@ def qnode_circuit(a): assert isinstance( qnode_transformed.transform_program.pop_front(), qml.transforms.core.TransformContainer ) - assert not dispatched_transform.is_informative + assert dispatched_transform.is_informative is False def test_integration_dispatcher_with_informative_transform(self): """Test that no error is raised with the transform function and that the transform dispatcher returns @@ -276,40 +344,6 @@ def qnode_circuit(a): # pylint:disable=unused-variable qml.RZ(a, wires=1) return qml.expval(qml.PauliZ(wires=0)) - def test_equality(self): - """Tests that we can compare TransformContainer objects with the '==' and '!=' operators.""" - - t1 = TransformContainer( - qml.transforms.compile.transform, kwargs={"num_passes": 2, "expand_depth": 1} - ) - t2 = TransformContainer( - qml.transforms.compile.transform, kwargs={"num_passes": 2, "expand_depth": 1} - ) - t3 = TransformContainer( - qml.transforms.transpile.transform, kwargs={"coupling_map": [(0, 1), (1, 2)]} - ) - t4 = TransformContainer( - qml.transforms.compile.transform, kwargs={"num_passes": 2, "expand_depth": 2} - ) - - t5 = TransformContainer(qml.transforms.merge_rotations.transform, args=(1e-6,)) - t6 = TransformContainer(qml.transforms.merge_rotations.transform, args=(1e-7,)) - - # test for equality of identical transformers - assert t1 == t2 - - # test for inequality of different transformers - assert t1 != t3 - assert t2 != t3 - assert t1 != 2 - assert t1 != t4 - assert t5 != t6 - assert t5 != t1 - - # Test equality with the same args - t5_copy = TransformContainer(qml.transforms.merge_rotations.transform, args=(1e-6,)) - assert t5 == t5_copy - def test_queuing_qfunc_transform(self): """Test that queuing works with the transformed quantum function.""" @@ -437,28 +471,6 @@ def test_dispatched_transform_attribute(self): assert dispatched_transform.expand_transform is None assert dispatched_transform.classical_cotransform is None - def test_the_transform_container_attributes(self): - """Test the transform container attributes.""" - container = qml.transforms.core.TransformContainer( - first_valid_transform, args=[0], kwargs={}, classical_cotransform=None - ) - - q_transform, args, kwargs, cotransform, is_informative, final_transform = container - - assert q_transform is first_valid_transform - assert args == [0] - assert kwargs == {} - assert cotransform is None - assert not is_informative - assert not final_transform - - assert container.transform is first_valid_transform - assert container.args == [0] - assert not container.kwargs - assert container.classical_cotransform is None - assert not container.is_informative - assert not container.final_transform - @pytest.mark.parametrize("valid_transform", valid_transforms) def test_custom_qnode_transform(self, valid_transform): """Test that the custom qnode transform is correctly executed""" @@ -620,3 +632,29 @@ def custom_transform( # pylint:disable=unused-variable tape = tape.copy() tape._ops.pop(index) # pylint:disable=protected-access return [tape], lambda x: x + + +def test_expand_fn_transform(): + """Tests the expand_fn_transform.""" + + def my_expand_fn(tape): + """my docstring.""" + return qml.tape.QuantumScript( + tape.operations + [qml.PauliX(0)], tape.measurements, tape.shots + ) + + t = qml.transforms.core.expand_fn_transform(my_expand_fn) + + assert isinstance(t, TransformDispatcher) + tape = qml.tape.QuantumScript([qml.S(0)], [qml.expval(qml.PauliZ(0))], shots=50) + + batch, fn = t(tape) + assert len(batch) == 1 + expected = qml.tape.QuantumScript( + [qml.S(0), qml.PauliX(0)], [qml.expval(qml.PauliZ(0))], shots=50 + ) + assert qml.equal(batch[0], expected) + assert fn(("a",)) == "a" + + assert repr(t) == "" + assert t.__doc__ == "my docstring." diff --git a/tests/transforms/test_experimental/test_transform_program.py b/tests/transforms/test_experimental/test_transform_program.py index 4f89fe305d9..338323244a0 100644 --- a/tests/transforms/test_experimental/test_transform_program.py +++ b/tests/transforms/test_experimental/test_transform_program.py @@ -133,6 +133,41 @@ def test_iter_program(self): assert isinstance(elem, TransformContainer) assert elem.transform is first_valid_transform + def test_getitem(self): + """Tests for the getitem dunder.""" + + t0 = TransformContainer(transform=first_valid_transform) + t1 = TransformContainer(transform=second_valid_transform) + t2 = TransformContainer(transform=informative_transform) + program = TransformProgram([t0, t1, t2]) + + assert program[0] == t0 + assert program[1] == t1 + assert program[2] == t2 + + assert program[:2] == TransformProgram([t0, t1]) + assert program[::-1] == TransformProgram([t2, t1, t0]) + + def test_contains(self): + """Test that we can check whether a transform or transform container exists in a transform.""" + + t0 = TransformContainer(transform=first_valid_transform) + t1 = TransformContainer(transform=second_valid_transform) + t2 = TransformContainer(transform=informative_transform) + program = TransformProgram([t0, t1, t2]) + + assert first_valid_transform in program + assert second_valid_transform in program + assert informative_transform in program + assert qml.compile not in program + + assert t0 in program + assert t1 in program + assert t2 in program + + t_not = TransformContainer(transform=qml.compile) + assert t_not not in program + def test_add_single_programs(self): """Test adding two transform programs""" transform_program1 = TransformProgram() diff --git a/tests/workflow/test_construct_batch.py b/tests/workflow/test_construct_batch.py new file mode 100644 index 00000000000..dc9ce3252ab --- /dev/null +++ b/tests/workflow/test_construct_batch.py @@ -0,0 +1,125 @@ +# Copyright 2018-2024 Xanadu Quantum Technologies Inc. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +""" +Contains tests for the `qml.workflow.transform_program` getter. + +""" +from functools import partial + +import pennylane as qml +from pennylane.transforms.core.transform_dispatcher import TransformContainer +from pennylane.transforms.core.transform_program import TransformProgram +from pennylane.workflow import transform_program + + +class TestTransformProgramGetter: + def test_transform_program_gradient_fn(self): + """Tests for the transform program when the gradient_fn is a transform.""" + + dev = qml.device("default.qubit", wires=4) + + @partial(qml.transforms.compile, num_passes=2) + @partial(qml.transforms.merge_rotations, atol=1e-5) + @qml.transforms.cancel_inverses + @qml.qnode(dev, diff_method="parameter-shift", shifts=2) + def circuit(): + return qml.expval(qml.PauliZ(0)) + + expected_p0 = qml.transforms.core.TransformContainer( + qml.transforms.cancel_inverses.transform + ) + expected_p1 = qml.transforms.core.TransformContainer( + qml.transforms.merge_rotations.transform, kwargs={"atol": 1e-5} + ) + expected_p2 = qml.transforms.core.TransformContainer( + qml.transforms.compile.transform, kwargs={"num_passes": 2} + ) + + ps_expand_fn = qml.transforms.core.TransformContainer( + qml.gradients.param_shift.expand_transform, kwargs={"shifts": 2} + ) + + p0 = transform_program(circuit, level=0) + assert isinstance(p0, TransformProgram) + assert len(p0) == 0 + + p0 = transform_program(circuit, level="top") + assert isinstance(p0, TransformProgram) + assert len(p0) == 0 + + p_grad = transform_program(circuit, level="gradient") + assert isinstance(p_grad, TransformProgram) + assert len(p_grad) == 4 + assert p_grad == TransformProgram([expected_p0, expected_p1, expected_p2, ps_expand_fn]) + + p_dev = transform_program(circuit, level="device") + assert isinstance(p_grad, TransformProgram) + p_default = transform_program(circuit) + p_none = transform_program(circuit, None) + assert p_dev == p_default + assert p_none == p_dev + assert len(p_dev) == 9 + assert p_dev == p_grad + dev.preprocess()[0] + + # slicing + p_sliced = transform_program(circuit, slice(2, 7, 2)) + assert len(p_sliced) == 3 + assert p_sliced[0].transform == qml.compile.transform + assert p_sliced[1].transform == qml.devices.preprocess.validate_device_wires.transform + assert p_sliced[2].transform == qml.devices.preprocess.decompose.transform + + def test_transform_program_device_gradient(self): + """Test the trnsform program contents when using a device derivative.""" + + dev = qml.device("default.qubit") + + @qml.transforms.sum_expand + @qml.qnode(dev, diff_method="adjoint", device_vjp=False) + def circuit(x): + qml.RX(x, 0) + return qml.expval(qml.PauliZ(0)) + + full_prog = transform_program(circuit) + assert len(full_prog) == 13 + + config = qml.devices.ExecutionConfig( + gradient_method="adjoint", use_device_jacobian_product=False + ) + dev_program = dev.preprocess(config)[0] + + expected = TransformProgram() + expected.add_transform(qml.transforms.sum_expand) + expected += dev_program + assert full_prog == expected + + def test_transform_program_legacy_device_interface(self): + """Test the contents of the transform program with the legacy device interface.""" + + dev = qml.device("default.qubit.legacy", wires=5) + + @qml.transforms.merge_rotations + @qml.qnode(dev, diff_method="backprop") + def circuit(x): + qml.RX(x, wires=0) + return qml.expval(qml.PauliZ(0)) + + program = transform_program(circuit) + + m1 = TransformContainer(qml.transforms.merge_rotations.transform) + m2 = TransformContainer(dev.batch_transform) + assert program[0:2] == TransformProgram([m1, m2]) + + # a little hard to check the contents of a expand_fn_transform + # this is the best proxy I can find + assert program[2].transform.__wrapped__ == dev.expand_fn From 6bd22dcf36e2711764db72eab530f0d542923ec6 Mon Sep 17 00:00:00 2001 From: albi3ro Date: Mon, 22 Jan 2024 17:30:02 -0500 Subject: [PATCH 02/19] fixing some tests --- .../transforms/core/transform_program.py | 5 +- pennylane/workflow/construct_batch.py | 35 ++++---- .../test_transform_program.py | 81 +++++++++++-------- tests/workflow/test_construct_batch.py | 10 +++ 4 files changed, 82 insertions(+), 49 deletions(-) diff --git a/pennylane/transforms/core/transform_program.py b/pennylane/transforms/core/transform_program.py index 9f288eb4314..cf1e5f6d74b 100644 --- a/pennylane/transforms/core/transform_program.py +++ b/pennylane/transforms/core/transform_program.py @@ -210,7 +210,10 @@ def push_back(self, transform_container: TransformContainer): # Program can only contain one informative transform and at the end of the program if self.has_final_transform: - raise TransformError("The transform program already has a terminal transform.") + if transform_container.final_transform: + raise TransformError("The transform program already has a terminal transform.") + self._transform_program.insert(-1, transform_container) + return self._transform_program.append(transform_container) def insert_front(self, transform_container: TransformContainer): diff --git a/pennylane/workflow/construct_batch.py b/pennylane/workflow/construct_batch.py index ba4d71fbc8b..930f61e7cbe 100644 --- a/pennylane/workflow/construct_batch.py +++ b/pennylane/workflow/construct_batch.py @@ -55,6 +55,7 @@ def transform_program(qnode: "QNode", level=None) -> "qml.transforms.core.Transf dev = qml.device('default.qubit', wires=4) + @qml.metric_tensor @qml.transforms.merge_rotations @qml.transforms.cancel_inverses @qml.qnode(dev, diff_method="parameter-shift", shifts=np.pi / 4) @@ -64,9 +65,9 @@ def circuit(): By default, we get the full transform program: >>> qml.workflow.transform_program(circuit) - TransformProgram(cancel_inverses, merge_rotations, _expand_transform_param_shift, + TransformProgram(compile, _expand_metric_tensor, _expand_transform_param_shift, validate_device_wires, defer_measurements, decompose, validate_measurements, - validate_observables) + validate_observables, metric_tensor) The `"user"` transforms are the one's manually applied to the qnode, :class:`~.cancel_inverses` and :class:`~.merge_rotations`. @@ -108,18 +109,22 @@ def circuit(): """ full_transform_program = _get_full_transform_program(qnode) + num_user = len(qnode.transform_program) + if qnode.transform_program.has_final_transform: + # final transform is placed after device transforms + num_user -= 1 + if level == "device": - level = None + level = -1 if full_transform_program.has_final_transform else None elif level == "top": level = 0 elif level == "user": - level = len(qnode.transform_program) + level = num_user - 1 if qnode.transform_program.has_final_transform else num_user elif level == "gradient": if getattr(qnode.gradient_fn, "expand_transform", False): - level = slice(0, len(qnode.transform_program) + 1) + level = slice(0, num_user + 1) else: - level = slice(0, len(qnode.transform_program)) - + level = slice(0, num_user) if level is None or isinstance(level, int): level = slice(0, level) return full_transform_program[level] @@ -141,6 +146,8 @@ def construct_batch(qnode: QNode, level: Union[None, str, int, slice] = "user") Callable: a function with the same call signature as the initial quantum function. This function returns a batch (tuple) of tapes and postprocessing function. + **See also:** :func:`pennylane.workflow.transform_program` to see the contents of the transform program for a specified level. + Suppose we have a device with several user transforms. .. code-block:: python @@ -157,7 +164,7 @@ def circuit(): We can inspect what the device will execute with: - >>> batch, fn = construct_batch(circuit, expansion_strategy="device")(1.23) + >>> batch, fn = construct_batch(circuit, level="device")(1.23) >>> batch[0].circuit [SWAP(wires=[0, 2]), SWAP(wires=[1, 2]), @@ -173,16 +180,16 @@ def circuit(): Or what the parameter shift gradient transform will be applied to: - >>> batch, fn = construct_batch(circuit, xpansion_strategy="gradient")(1.23) + >>> batch, fn = construct_batch(circuit, level="gradient")(1.23) >>> batch[0].circuit [Permute(wires=[0, 1, 2]), RY(tensor(1., requires_grad=True), wires=[0]), RX(tensor(2., requires_grad=True), wires=[1]), expval(PauliX(wires=[0]) + PauliY(wires=[0]))] - We can inpsect what was directly captured from the qfunc with ``expansion_strategy=0``. + We can inpsect what was directly captured from the qfunc with ``level=0``. - >>> batch, fn = construct_batch(circuit, expansion_strategy=0)(1.23) + >>> batch, fn = construct_batch(circuit, level=0)(1.23) >>> batch[0].circuit [Permute(wires=[0, 1, 2]), RandomLayers(tensor([[1., 2.]], requires_grad=True), wires=[0, 1]), @@ -193,9 +200,9 @@ def circuit(): expval(PauliX(wires=[0]) + PauliY(wires=[0]))] And iterate though stages in the transform program with different integers. - If we request ``expansion_strategy=1``, the ``cancel_inverses`` transform has been applied. + If we request ``level=1``, the ``cancel_inverses`` transform has been applied. - >>> batch, fn = construct_batch(circuit, expansion_strategy=1)(1.23) + >>> batch, fn = construct_batch(circuit, level=1)(1.23) >>> batch[0].circuit [Permute(wires=[0, 1, 2]), RandomLayers(tensor([[1., 2.]], requires_grad=True), wires=[0, 1]), @@ -206,7 +213,7 @@ def circuit(): We can also slice into a subset of the transform program. ``slice(1, None)`` would skip the first user transform ``cancel_inverses``: - >>> batch, fn = construct_batch(circuit, expansion_strategy=slice(1,None))(1.23, include_permute=False) + >>> batch, fn = construct_batch(circuit, level=slice(1,None))(1.23, include_permute=False) >>> batch[0].circuit [RY(tensor(1., requires_grad=True), wires=[0]), RX(tensor(2., requires_grad=True), wires=[1]), diff --git a/tests/transforms/test_experimental/test_transform_program.py b/tests/transforms/test_experimental/test_transform_program.py index 338323244a0..63c73d58de1 100644 --- a/tests/transforms/test_experimental/test_transform_program.py +++ b/tests/transforms/test_experimental/test_transform_program.py @@ -156,9 +156,9 @@ def test_contains(self): t2 = TransformContainer(transform=informative_transform) program = TransformProgram([t0, t1, t2]) - assert first_valid_transform in program - assert second_valid_transform in program - assert informative_transform in program + assert t0 in program + assert t1 in program + assert t2 in program assert qml.compile not in program assert t0 in program @@ -307,6 +307,35 @@ def test_repr_program(self): + ")" ) + def test_equality(self): + """Tests that we can compare TransformProgram objects with the '==' and '!=' operators.""" + t1 = TransformContainer( + qml.transforms.compile.transform, kwargs={"num_passes": 2, "expand_depth": 1} + ) + t2 = TransformContainer( + qml.transforms.compile.transform, kwargs={"num_passes": 2, "expand_depth": 1} + ) + t3 = TransformContainer( + qml.transforms.transpile.transform, kwargs={"coupling_map": [(0, 1), (1, 2)]} + ) + + p1 = TransformProgram([t1, t3]) + p2 = TransformProgram([t2, t3]) + p3 = TransformProgram([t3, t2]) + + # test for equality of identical objects + assert p1 == p2 + # test for inequality of different objects + assert p1 != p3 + assert p1 != t1 + + # Test inequality with different transforms + t4 = TransformContainer( + qml.transforms.transpile.transform, kwargs={"coupling_map": [(0, 1), (2, 3)]} + ) + p4 = TransformProgram([t1, t4]) + assert p1 != p4 + class TestTransformProgram: """Test the transform program class and its method.""" @@ -500,52 +529,36 @@ def test_insert_transform_with_expand(self): assert transform_program[1].transform is first_valid_transform def test_valid_transforms(self): - """Test that it is only possible to create valid transforms.""" + """Test adding transforms to a program with a terminal transform.""" transform_program = TransformProgram() transform1 = TransformContainer(transform=first_valid_transform, is_informative=True) transform_program.push_back(transform1) + t_normal = TransformContainer(transform=second_valid_transform) + transform_program.push_back(t_normal) + print(transform_program) + assert len(transform_program) == 2 + assert transform_program[0] is t_normal + assert transform_program[1] is transform1 + + t_normal2 = TransformContainer(transform=first_valid_transform) + transform_program.push_back(t_normal2) + assert transform_program[0] is t_normal + assert transform_program[1] is t_normal2 + assert transform_program[2] is transform1 + with pytest.raises( TransformError, match="The transform program already has a terminal transform." ): transform_program.push_back(transform1) - transform2 = TransformContainer(transform=second_valid_transform, is_informative=False) + transform2 = TransformContainer(transform=second_valid_transform, final_transform=True) with pytest.raises( TransformError, match="The transform program already has a terminal transform." ): transform_program.push_back(transform2) - def test_equality(self): - """Tests that we can compare TransformProgram objects with the '==' and '!=' operators.""" - t1 = TransformContainer( - qml.transforms.compile.transform, kwargs={"num_passes": 2, "expand_depth": 1} - ) - t2 = TransformContainer( - qml.transforms.compile.transform, kwargs={"num_passes": 2, "expand_depth": 1} - ) - t3 = TransformContainer( - qml.transforms.transpile.transform, kwargs={"coupling_map": [(0, 1), (1, 2)]} - ) - - p1 = TransformProgram([t1, t3]) - p2 = TransformProgram([t2, t3]) - p3 = TransformProgram([t3, t2]) - - # test for equality of identical objects - assert p1 == p2 - # test for inequality of different objects - assert p1 != p3 - assert p1 != t1 - - # Test inequality with different transforms - t4 = TransformContainer( - qml.transforms.transpile.transform, kwargs={"coupling_map": [(0, 1), (2, 3)]} - ) - p4 = TransformProgram([t1, t4]) - assert p1 != p4 - class TestTransformProgramCall: """Tests for calling a TransformProgram on a batch of quantum tapes.""" diff --git a/tests/workflow/test_construct_batch.py b/tests/workflow/test_construct_batch.py index dc9ce3252ab..72ad178330e 100644 --- a/tests/workflow/test_construct_batch.py +++ b/tests/workflow/test_construct_batch.py @@ -123,3 +123,13 @@ def circuit(x): # a little hard to check the contents of a expand_fn_transform # this is the best proxy I can find assert program[2].transform.__wrapped__ == dev.expand_fn + + def test_transform_program_final_transform(self): + """Test that gradient preprocessing and device transform occur before a final transform.""" + + @qml.metric_tensor + @qml.compile + @qml.qnode(qml.device("default.qubit"), diff_method="parameter-shift") + def circuit(): + qml.IsingXX(1.234, wires=(0, 1)) + return qml.expval(qml.PauliZ(0)), qml.expval(qml.PauliX(0)) From 335da6e81db078c87e5094f546f622df04d68b2a Mon Sep 17 00:00:00 2001 From: albi3ro Date: Tue, 23 Jan 2024 17:26:09 -0500 Subject: [PATCH 03/19] adding graphic and tests --- doc/_static/transforms_order.png | Bin 0 -> 50426 bytes doc/_static/transforms_order.svg | 250 +++++++++++++++++++++++++ pennylane/workflow/construct_batch.py | 36 +++- tests/workflow/test_construct_batch.py | 72 ++++++- 4 files changed, 347 insertions(+), 11 deletions(-) create mode 100644 doc/_static/transforms_order.png create mode 100644 doc/_static/transforms_order.svg diff --git a/doc/_static/transforms_order.png b/doc/_static/transforms_order.png new file mode 100644 index 0000000000000000000000000000000000000000..c39f720777825d39e0ecf82e2662887d78723b67 GIT binary patch literal 50426 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 z≫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 literal 0 HcmV?d00001 diff --git a/doc/_static/transforms_order.svg b/doc/_static/transforms_order.svg new file mode 100644 index 00000000000..64d9400a0fb --- /dev/null +++ b/doc/_static/transforms_order.svg @@ -0,0 +1,250 @@ + + + + + + + + + + + + + + + + + + Tapes + Results + + Transform 1 + + Transform 2 + + gradient + + device + + Final + + ML Boundary + + + diff --git a/pennylane/workflow/construct_batch.py b/pennylane/workflow/construct_batch.py index 930f61e7cbe..351e7eed7f6 100644 --- a/pennylane/workflow/construct_batch.py +++ b/pennylane/workflow/construct_batch.py @@ -51,13 +51,24 @@ def transform_program(qnode: "QNode", level=None) -> "qml.transforms.core.Transf TransformProrgram: the transform program corresponding to t + The transforms are organized as: + + .. image:: ../../_static/transforms_order.png + :align: center + :width: 800px + :target: javascript:void(0); + + where ``transform1`` is first applied to the ``QNode`` followed by ``transform2``. First user transforms are run on the tapes, + followed by the gradient expansion, followed by the device expansion. "Final" transforms, like ``param_shift`` and ``metric_tensor``, + always occur at the end of the program. + .. code-block:: python dev = qml.device('default.qubit', wires=4) - @qml.metric_tensor - @qml.transforms.merge_rotations - @qml.transforms.cancel_inverses + @qml.metric_tensor # final transform + @qml.transforms.merge_rotations # transform 2 + @qml.transforms.cancel_inverses # transform 1 @qml.qnode(dev, diff_method="parameter-shift", shifts=np.pi / 4) def circuit(): return qml.expval(qml.PauliZ(0)) @@ -119,7 +130,7 @@ def circuit(): elif level == "top": level = 0 elif level == "user": - level = num_user - 1 if qnode.transform_program.has_final_transform else num_user + level = num_user elif level == "gradient": if getattr(qnode.gradient_fn, "expand_transform", False): level = slice(0, num_user + 1) @@ -152,15 +163,20 @@ def construct_batch(qnode: QNode, level: Union[None, str, int, slice] = "user") .. code-block:: python - x = np.array([0.1, 0.2]) - - dev = qml.device('default.qubit', wires=4) - + @qml.transforms.undo_swaps @qml.transforms.merge_rotations @qml.transforms.cancel_inverses + @partial(decompose, stopping_condition=lambda op: op.name not in {"GroverOperator", "GlobalPhase"}) @qml.qnode(dev, diff_method="parameter-shift", shifts=np.pi / 4) - def circuit(): - return qml.expval(qml.PauliZ(0)) + def circuit(x): + qml.GroverOperator(wires=(0,1,2)) + qml.RandomLayers(qml.numpy.array([[1.0, 2.0]]), wires=(0,1)) + qml.RX(x, wires=0) + qml.RX(-x, wires=0) + qml.SWAP((0,1)) + qml.PauliX(0) + qml.PauliX(0) + return qml.expval(qml.PauliX(0) + qml.PauliY(0)) We can inspect what the device will execute with: diff --git a/tests/workflow/test_construct_batch.py b/tests/workflow/test_construct_batch.py index 72ad178330e..166af95dbe4 100644 --- a/tests/workflow/test_construct_batch.py +++ b/tests/workflow/test_construct_batch.py @@ -17,10 +17,12 @@ """ from functools import partial +import numpy as np + import pennylane as qml from pennylane.transforms.core.transform_dispatcher import TransformContainer from pennylane.transforms.core.transform_program import TransformProgram -from pennylane.workflow import transform_program +from pennylane.workflow import transform_program, construct_batch class TestTransformProgramGetter: @@ -133,3 +135,71 @@ def test_transform_program_final_transform(self): def circuit(): qml.IsingXX(1.234, wires=(0, 1)) return qml.expval(qml.PauliZ(0)), qml.expval(qml.PauliX(0)) + + user_program = transform_program(circuit, level="user") + assert len(user_program) == 2 + assert user_program[0].transform == qml.compile.transform + assert user_program[1].transform == qml.metric_tensor.expand_transform + + grad_program = transform_program(circuit, level="gradient") + assert len(grad_program) == 3 + assert grad_program[0].transform == qml.compile.transform + assert grad_program[1].transform == qml.metric_tensor.expand_transform + assert grad_program[2].transform == qml.gradients.param_shift.expand_transform + + dev_program = transform_program(circuit, level="device") + assert len(dev_program) == 3 + len(circuit.device.preprocess()[0]) # currently 8 + assert qml.metric_tensor not in dev_program + + full = transform_program(circuit) + assert full[-1].transform == qml.metric_tensor.transform + + +class TestConstructBatch: + """Tests for the construct_batch function.""" + + def test_level_zero(self): + """Test that level zero is purely the queued circuit.""" + + @qml.compile + @qml.qnode(qml.device("default.qubit"), diff_method="parameter-shift") + def circuit(order): + qml.Permute(order, wires=(0, 1, 2)) + qml.PauliX(0) + qml.PauliX(0) + return qml.state() + + batch, fn = construct_batch(circuit, level=0)([2, 1, 0], shots=10) + + assert len(batch) == 1 + expected = qml.tape.QuantumScript( + [qml.Permute([2, 1, 0], wires=(0, 1, 2)), qml.PauliX(0), qml.PauliX(0)], + [qml.state()], + shots=10, + ) + assert qml.equal(batch[0], expected) + + assert fn(("a,")) == "a" + + def test_user_transforms(self): + """Test that user transforms can be selected and applied.""" + + @qml.transforms.cancel_inverses + @qml.qnode(qml.device("default.qubit"), diff_method="parameter-shift") + def circuit(weights): + qml.RandomLayers(weights, wires=(0, 1)) + qml.PauliX(0) + qml.PauliX(0) + return qml.state() + + weights = np.array([[1.0, 2.0]]) + + for level in ("user", 1): + batch, fn = construct_batch(circuit, level=level)(weights, shots=50) + assert len(batch) == 1 + + expected = qml.tape.QuantumScript( + [qml.RandomLayers(weights, wires=(0, 1))], [qml.state()], shots=50 + ) + assert qml.equal(batch[0], expected) + assert fn(("a",)) == "a" From 127e2b01d2e1337124e9df704bb6d6f58e86a187 Mon Sep 17 00:00:00 2001 From: albi3ro Date: Wed, 24 Jan 2024 15:58:43 -0500 Subject: [PATCH 04/19] finishing up testing --- pennylane/templates/subroutines/permute.py | 3 + pennylane/workflow/construct_batch.py | 85 ++++--- .../test_subroutines/test_permute.py | 5 + tests/workflow/test_construct_batch.py | 233 +++++++++++++++--- 4 files changed, 260 insertions(+), 66 deletions(-) diff --git a/pennylane/templates/subroutines/permute.py b/pennylane/templates/subroutines/permute.py index 394fa2f6418..569d977f195 100644 --- a/pennylane/templates/subroutines/permute.py +++ b/pennylane/templates/subroutines/permute.py @@ -138,6 +138,9 @@ def circuit(): """ + def __repr__(self): + return f"Permute({self.hyperparameters['permutation']}, wires={self.wires.tolist()})" + num_wires = AnyWires grad_method = None diff --git a/pennylane/workflow/construct_batch.py b/pennylane/workflow/construct_batch.py index 351e7eed7f6..c332451aeb2 100644 --- a/pennylane/workflow/construct_batch.py +++ b/pennylane/workflow/construct_batch.py @@ -39,7 +39,7 @@ def transform_program(qnode: "QNode", level=None) -> "qml.transforms.core.Transf """Extract a transform program at a designated level. Args: - qnode (QNode): ? + qnode (QNode): the qnode to get the transform program for. level (None, str, int, slice): And indication * ``None``: use the full transform program @@ -64,7 +64,7 @@ def transform_program(qnode: "QNode", level=None) -> "qml.transforms.core.Transf .. code-block:: python - dev = qml.device('default.qubit', wires=4) + dev = qml.device('default.qubit') @qml.metric_tensor # final transform @qml.transforms.merge_rotations # transform 2 @@ -73,14 +73,14 @@ def transform_program(qnode: "QNode", level=None) -> "qml.transforms.core.Transf def circuit(): return qml.expval(qml.PauliZ(0)) - By default, we get the full transform program: + By default, we get the full transform program. This can be manaully specified by ``level=None``. >>> qml.workflow.transform_program(circuit) TransformProgram(compile, _expand_metric_tensor, _expand_transform_param_shift, validate_device_wires, defer_measurements, decompose, validate_measurements, validate_observables, metric_tensor) - The `"user"` transforms are the one's manually applied to the qnode, :class:`~.cancel_inverses` and + The ``"user"`` transforms are the ones manually applied to the qnode, :class:`~.cancel_inverses` and :class:`~.merge_rotations`. >>> qml.workflow.transform_program(circuit, level="user") @@ -93,29 +93,36 @@ def circuit(): >>> qml.workflow.transform_program(circuit, level="gradient") TransformProgram(cancel_inverses, merge_rotations, _expand_transform_param_shift) - ``"device"`` includes all transforms in the full transform program. This corresponds to the circuits that will - be sent to the device to execute. + ``"device"`` includes all transforms except for a ``"final"`` transform, if it exists. This usually + corresponds to the circuits that will be sent to the device to execute. >>> qml.workflow.transform_program(circuit, level="device") TransformProgram(cancel_inverses, merge_rotations, _expand_transform_param_shift, validate_device_wires, defer_measurements, decompose, validate_measurements, validate_observables) + ``"top"`` and ``0`` both return empty transform programs. + >>> qml.workflow.transform_program(circuit, level="top") TransformProgram() + >>> qml.workflow.transform_program(circuit, level=0) + TransformProgram() + + The ``level`` can also be any integer, corresponding to a number of transforms in the program. >>> qml.workflow.transform_program(circuit, level=2) TransformProgram(cancel_inverses, merge_rotations) - ``level`` can also accept a ``slice`` object to select out any arbitrary subset of the transform program. This allows you to select - different starting transforms or strides. Fro example, you can get the transform program with a reversed order. + ``level`` can also accept a ``slice`` object to select out any arbitrary subset of the + transform program. This allows you to select different starting transforms or strides. + For example, you can skip the first transform or reverse the order: >>> qml.workflow.transform_program(circuit, level=slice(1,3)) TransformProgram(merge_rotations, _expand_transform_param_shift) - >>> qml.workflow.transform_program(circuit, level=slice(None, 0, -1)) - TransformProgram(validate_observables, validate_measurements, decompose, - defer_measurements, validate_device_wires, _expand_transform_param_shift, merge_rotations) - + >>> qml.workflow.transform_program(circuit, level=slice(None, None, -1)) + TransformProgram(metric_tensor, validate_observables, validate_measurements, + decompose, defer_measurements, validate_device_wires, _expand_transform_param_shift, + _expand_metric_tensor, merge_rotations, cancel_inverses) """ full_transform_program = _get_full_transform_program(qnode) @@ -136,6 +143,10 @@ def circuit(): level = slice(0, num_user + 1) else: level = slice(0, num_user) + elif isinstance(level, str): + raise ValueError( + f"level {level} not recognized. Acceptable strings are 'device', 'top', 'user', and 'gradient'." + ) if level is None or isinstance(level, int): level = slice(0, level) return full_transform_program[level] @@ -145,11 +156,11 @@ def construct_batch(qnode: QNode, level: Union[None, str, int, slice] = "user") """Construct the batch of tapes and post processing for a designated stage in the transform program. Args: - qnode (QNode): ? not sure how to best define qnode here ? + qnode (QNode): the qnode we want to get the tapes and post-processing for. level (None, str, int, slice): And indication * ``None``: use the full transform program - * ``str``: Acceptable keys are ``"user"``, ``"device"``, and ``"gradient"`` + * ``str``: Acceptable keys are ``"top"``, ``"user"``, ``"device"``, and ``"gradient"`` * ``int``: How many transforms to include, starting from the front of the program * ``slice``: a slice to select out components of the transform program. @@ -157,7 +168,7 @@ def construct_batch(qnode: QNode, level: Union[None, str, int, slice] = "user") Callable: a function with the same call signature as the initial quantum function. This function returns a batch (tuple) of tapes and postprocessing function. - **See also:** :func:`pennylane.workflow.transform_program` to see the contents of the transform program for a specified level. + ..seealso:: :func:`pennylane.workflow.transform_program` to inspect the contents of the transform program for a specified level. Suppose we have a device with several user transforms. @@ -166,10 +177,8 @@ def construct_batch(qnode: QNode, level: Union[None, str, int, slice] = "user") @qml.transforms.undo_swaps @qml.transforms.merge_rotations @qml.transforms.cancel_inverses - @partial(decompose, stopping_condition=lambda op: op.name not in {"GroverOperator", "GlobalPhase"}) @qml.qnode(dev, diff_method="parameter-shift", shifts=np.pi / 4) def circuit(x): - qml.GroverOperator(wires=(0,1,2)) qml.RandomLayers(qml.numpy.array([[1.0, 2.0]]), wires=(0,1)) qml.RX(x, wires=0) qml.RX(-x, wires=0) @@ -182,60 +191,62 @@ def circuit(x): >>> batch, fn = construct_batch(circuit, level="device")(1.23) >>> batch[0].circuit - [SWAP(wires=[0, 2]), - SWAP(wires=[1, 2]), - RY(tensor(1., requires_grad=True), wires=[0]), - RX(tensor(2., requires_grad=True), wires=[1]), - expval(PauliX(wires=[0]) + PauliY(wires=[0]))] + [RY(tensor(1., requires_grad=True), wires=[1]), + RX(tensor(2., requires_grad=True), wires=[0]), + expval( (1) [X0] + + (1) [Y0])] These tapes can be natively executed by the device, though with non-backprop devices the parameters will need to be converted to numpy with :func:`~.convert_to_numpy_parameters`. >>> fn(dev.execute(batch)) - (tensor(0.84147098, requires_grad=True),) + (tensor(-0.90929743, requires_grad=True),) Or what the parameter shift gradient transform will be applied to: >>> batch, fn = construct_batch(circuit, level="gradient")(1.23) >>> batch[0].circuit - [Permute(wires=[0, 1, 2]), - RY(tensor(1., requires_grad=True), wires=[0]), - RX(tensor(2., requires_grad=True), wires=[1]), - expval(PauliX(wires=[0]) + PauliY(wires=[0]))] + [RY(tensor(1., requires_grad=True), wires=[1]), + RX(tensor(2., requires_grad=True), wires=[0]), + expval( (1) [X0] + + (1) [Y0])] We can inpsect what was directly captured from the qfunc with ``level=0``. >>> batch, fn = construct_batch(circuit, level=0)(1.23) >>> batch[0].circuit - [Permute(wires=[0, 1, 2]), - RandomLayers(tensor([[1., 2.]], requires_grad=True), wires=[0, 1]), + [RandomLayers(tensor([[1., 2.]], requires_grad=True), wires=[0, 1]), RX(1.23, wires=[0]), RX(-1.23, wires=[0]), + SWAP(wires=[0, 1]), PauliX(wires=[0]), PauliX(wires=[0]), - expval(PauliX(wires=[0]) + PauliY(wires=[0]))] + expval( (1) [X0] + + (1) [Y0])] And iterate though stages in the transform program with different integers. If we request ``level=1``, the ``cancel_inverses`` transform has been applied. >>> batch, fn = construct_batch(circuit, level=1)(1.23) >>> batch[0].circuit - [Permute(wires=[0, 1, 2]), - RandomLayers(tensor([[1., 2.]], requires_grad=True), wires=[0, 1]), + [RandomLayers(tensor([[1., 2.]], requires_grad=True), wires=[0, 1]), RX(1.23, wires=[0]), RX(-1.23, wires=[0]), - expval(PauliX(wires=[0]) + PauliY(wires=[0]))] + SWAP(wires=[0, 1]), + expval( (1) [X0] + + (1) [Y0])] We can also slice into a subset of the transform program. ``slice(1, None)`` would skip the first user transform ``cancel_inverses``: - >>> batch, fn = construct_batch(circuit, level=slice(1,None))(1.23, include_permute=False) + >>> batch, fn = construct_batch(circuit, level=slice(1,None))(1.23) >>> batch[0].circuit - [RY(tensor(1., requires_grad=True), wires=[0]), - RX(tensor(2., requires_grad=True), wires=[1]), + [RY(tensor(1., requires_grad=True), wires=[1]), + RX(tensor(2., requires_grad=True), wires=[0]), PauliX(wires=[0]), PauliX(wires=[0]), - expval(PauliX(wires=[0]) + PauliY(wires=[0]))] + expval( (1) [X0] + + (1) [Y0])] """ program = transform_program(qnode, level=level) diff --git a/tests/templates/test_subroutines/test_permute.py b/tests/templates/test_subroutines/test_permute.py index 6eefab22851..4bfa0dbc47b 100644 --- a/tests/templates/test_subroutines/test_permute.py +++ b/tests/templates/test_subroutines/test_permute.py @@ -26,6 +26,11 @@ def test_standard_validity(): qml.ops.functions.assert_valid(op) +def test_repr(): + op = qml.Permute([2, 1, 0], wires=(0, 1, 2)) + assert repr(op) == "Permute((2, 1, 0), wires=[0, 1, 2])" + + class TestDecomposition: """Tests that the template defines the correct decomposition.""" diff --git a/tests/workflow/test_construct_batch.py b/tests/workflow/test_construct_batch.py index 166af95dbe4..a670c17ca7f 100644 --- a/tests/workflow/test_construct_batch.py +++ b/tests/workflow/test_construct_batch.py @@ -16,6 +16,7 @@ """ from functools import partial +import pytest import numpy as np @@ -26,6 +27,16 @@ class TestTransformProgramGetter: + def test_bad_string_key(self): + """Test a value error is raised if a bad string key is provided.""" + + @qml.qnode(qml.device("default.qubit")) + def circuit(): + return qml.state() + + with pytest.raises(ValueError, match=r"level bah not recognized."): + transform_program(circuit, level="bah") + def test_transform_program_gradient_fn(self): """Tests for the transform program when the gradient_fn is a transform.""" @@ -155,51 +166,215 @@ def circuit(): assert full[-1].transform == qml.metric_tensor.transform +@qml.transforms.merge_rotations +@qml.transforms.cancel_inverses +@qml.qnode(qml.device("default.qubit"), diff_method="parameter-shift") +def circuit1(weights, order): + qml.RandomLayers(weights, wires=(0, 1)) + qml.Permute(order, wires=(0, 1, 2)) + qml.PauliX(0) + qml.PauliX(0) + qml.RX(0.1, wires=0) + qml.RX(-0.1, wires=0) + return qml.expval(qml.PauliX(0)) + + class TestConstructBatch: """Tests for the construct_batch function.""" def test_level_zero(self): """Test that level zero is purely the queued circuit.""" - @qml.compile - @qml.qnode(qml.device("default.qubit"), diff_method="parameter-shift") - def circuit(order): - qml.Permute(order, wires=(0, 1, 2)) - qml.PauliX(0) - qml.PauliX(0) - return qml.state() - - batch, fn = construct_batch(circuit, level=0)([2, 1, 0], shots=10) + order = [2, 1, 0] + weights = np.array([[1.0, 20]]) + batch, fn = construct_batch(circuit1, level=0)(weights, order, shots=10) assert len(batch) == 1 + expected_ops = [ + qml.RandomLayers(weights, wires=(0, 1)), + qml.Permute(order, wires=(0, 1, 2)), + qml.PauliX(0), + qml.PauliX(0), + qml.RX(0.1, wires=0), + qml.RX(-0.1, wires=0), + ] + expected = qml.tape.QuantumScript( - [qml.Permute([2, 1, 0], wires=(0, 1, 2)), qml.PauliX(0), qml.PauliX(0)], - [qml.state()], + expected_ops, + [qml.expval(qml.PauliX(0))], shots=10, ) assert qml.equal(batch[0], expected) - assert fn(("a,")) == "a" + assert fn(("a",)) == ("a",) - def test_user_transforms(self): - """Test that user transforms can be selected and applied.""" + def test_first_transform(self): + """Test that the first user transform can be selected by level=1""" - @qml.transforms.cancel_inverses - @qml.qnode(qml.device("default.qubit"), diff_method="parameter-shift") - def circuit(weights): - qml.RandomLayers(weights, wires=(0, 1)) - qml.PauliX(0) - qml.PauliX(0) - return qml.state() + weights = np.array([[1.0, 2.0]]) + order = [2, 1, 0] + + batch, fn = construct_batch(circuit1, level=1)(weights, order=order, shots=50) + assert len(batch) == 1 + + expected_ops = [ + qml.RandomLayers(weights, wires=(0, 1)), + qml.Permute(order, wires=(0, 1, 2)), + # cancel inverses + qml.RX(0.1, wires=0), + qml.RX(-0.1, wires=0), + ] + + expected = qml.tape.QuantumScript(expected_ops, [qml.expval(qml.PauliX(0))], shots=50) + assert qml.equal(batch[0], expected) + assert fn(("a",)) == ("a",) + + @pytest.mark.parametrize("level", (2, "user")) + def test_all_user_transforms(self, level): + """Test that all user transforms can be selected and run.""" weights = np.array([[1.0, 2.0]]) + order = [2, 1, 0] - for level in ("user", 1): - batch, fn = construct_batch(circuit, level=level)(weights, shots=50) - assert len(batch) == 1 + batch, fn = construct_batch(circuit1, level=level)(weights, order=order, shots=50) + assert len(batch) == 1 + + expected_ops = [ + qml.RandomLayers(weights, wires=(0, 1)), + qml.Permute(order, wires=(0, 1, 2)), + # cancel inverses + # merge rotations + ] - expected = qml.tape.QuantumScript( - [qml.RandomLayers(weights, wires=(0, 1))], [qml.state()], shots=50 - ) - assert qml.equal(batch[0], expected) - assert fn(("a",)) == "a" + expected = qml.tape.QuantumScript(expected_ops, [qml.expval(qml.PauliX(0))], shots=50) + assert qml.equal(batch[0], expected) + assert fn(("a",)) == ("a",) + + @pytest.mark.parametrize("level", (3, "gradient")) + def test_gradient_transforms(self, level): + """Test that the gradient transform can be selected with an integer or keyword.""" + weights = qml.numpy.array([[1.0, 2.0]], requires_grad=True) + order = [2, 1, 0] + batch, fn = construct_batch(circuit1, level=level)(weights=weights, order=order) + + expected = qml.tape.QuantumScript( + [ + qml.RY(qml.numpy.array(1), 0), + qml.RX(qml.numpy.array(2), 1), + qml.Permute(order, (0, 1, 2)), + ], + [qml.expval(qml.PauliX(0))], + ) + assert qml.equal(batch[0], expected) + assert len(batch) == 1 + assert fn(("a",)) == ("a",) + + @pytest.mark.parametrize("level", ("device", None)) + def test_device_transforms(self, level): + """Test that all device transforms can be run with the device keyword.""" + + weights = np.array([[1.0, 2.0]]) + order = [2, 1, 0] + + batch, fn = construct_batch(circuit1, level=level)(weights, order) + + expected = qml.tape.QuantumScript( + [qml.RY(1, 0), qml.RX(2, 1), qml.SWAP((0, 2))], [qml.expval(qml.PauliX(0))] + ) + assert qml.equal(batch[0], expected) + assert len(batch) == 1 + assert fn(("a",)) == ("a",) + + @pytest.mark.parametrize("level", ("device", None)) + def test_device_transforms_legacy_interface(self, level): + """Test that the device transforms can be selected with level=device or None.""" + + @qml.transforms.merge_rotations + @qml.qnode(qml.device("default.qubit.legacy", wires=2, shots=50)) + def circuit(order): + qml.Permute(order, wires=(0, 1, 2)) + qml.RX(0.5, wires=0) + qml.RX(-0.5, wires=0) + return qml.expval(qml.PauliX(0) + qml.PauliY(0)) + + batch, fn = construct_batch(circuit, level=level)((2, 1, 0)) + + expected0 = qml.tape.QuantumScript( + [qml.SWAP((0, 2))], [qml.expval(qml.PauliX(0))], shots=50 + ) + assert qml.equal(expected0, batch[0]) + expected1 = qml.tape.QuantumScript( + [qml.SWAP((0, 2))], [qml.expval(qml.PauliY(0))], shots=50 + ) + assert qml.equal(expected1, batch[1]) + assert len(batch) == 2 + + assert fn((1.0, 2.0)) == (3.0,) + + def test_final_transform(self): + """Test that the final transform is included when level=None.""" + + @qml.gradients.param_shift + @qml.transforms.merge_rotations + @qml.qnode(qml.device("default.qubit")) + def circuit(x): + qml.RX(x, 0) + qml.RX(x, 0) + return qml.expval(qml.PauliZ(0)) + + batch, fn = construct_batch(circuit, level=None)(0.5) + assert len(batch) == 2 + expected0 = qml.tape.QuantumScript( + [qml.RX(1.0 + np.pi / 2, 0)], [qml.expval(qml.PauliZ(0))] + ) + assert qml.equal(batch[0], expected0) + expected1 = qml.tape.QuantumScript( + [qml.RX(1.0 - np.pi / 2, 0)], [qml.expval(qml.PauliZ(0))] + ) + assert qml.equal(batch[1], expected1) + + dummy_res = (1.0, 2.0) + expected_res = (1.0 - 2.0) / 2 + assert qml.numpy.allclose(fn(dummy_res)[0], expected_res) + + def test_user_transform_multiple_tapes(self): + """Test a user transform that creates multiple tapes.""" + + @qml.transforms.split_non_commuting + @qml.qnode(qml.device("default.qubit", shots=10)) + def circuit(): + qml.S(0) + return qml.expval(qml.PauliX(0)), qml.expval(qml.PauliZ(0)), qml.expval(qml.PauliX(1)) + + batch, fn = construct_batch(circuit, level="user")() + + assert len(batch) == 2 + expected0 = qml.tape.QuantumScript( + [qml.S(0)], [qml.expval(qml.PauliX(0)), qml.expval(qml.PauliX(1))], shots=10 + ) + assert qml.equal(expected0, batch[0]) + + expected1 = qml.tape.QuantumScript([qml.S(0)], [qml.expval(qml.PauliZ(0))], shots=10) + assert qml.equal(expected1, batch[1]) + + dummy_res = (("x0", "x1"), "z0") + expected_res = (("x0", "z0", "x1"),) + assert fn(dummy_res) == expected_res + + def test_slicing_level(self): + @qml.transforms.merge_rotations + @qml.qnode(qml.device("default.qubit")) + def circuit(x): + qml.RX(x, 0) + qml.RX(x, 0) + return qml.expval(qml.PauliZ(0)) + + # by slicing starting at one, we do not run the merge rotations transform + batch, fn = construct_batch(circuit, slice(1, None))(0.5) + + assert len(batch) == 1 + expected = qml.tape.QuantumScript( + [qml.RX(0.5, 0), qml.RX(0.5, 0)], [qml.expval(qml.PauliZ(0))] + ) + assert qml.equal(batch[0], expected) + assert fn(("a",)) == ("a",) From 61fa6de21caf231a2c38f3aa74a38812f472d75b Mon Sep 17 00:00:00 2001 From: Christina Lee Date: Wed, 24 Jan 2024 15:59:42 -0500 Subject: [PATCH 05/19] Apply suggestions from code review Co-authored-by: Thomas R. Bromley <49409390+trbromley@users.noreply.github.com> --- doc/releases/changelog-dev.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md index c56defffc20..0c2b477993d 100644 --- a/doc/releases/changelog-dev.md +++ b/doc/releases/changelog-dev.md @@ -87,8 +87,10 @@ * Adds `qml.workflow.transform_program` and `qml.workflow.construct_batch` to inspect the transform program and batch of tapes at different stages. + [(#5084)](https://github.com/PennyLaneAI/pennylane/pull/5084) -* Adds a `qml.transforms.core.expand_fn_transform` that converts a tape-> tape function into a transform. +* Adds a `qml.transforms.core.expand_fn_transform` that converts a tape-to-tape function into a transform. + [(#5084)](https://github.com/PennyLaneAI/pennylane/pull/5084) * `CRX`, `CRY`, `CRZ`, `CROT`, and `ControlledPhaseShift` (i.e. `CPhaseShift`) now inherit from `ControlledOp`, giving them additional properties such as `control_wire` and `control_values`. Calling `qml.ctrl` on `RX`, `RY`, `RZ`, `Rot`, and `PhaseShift` with a single control wire will return gates of types `CRX`, `CRY`, etc. as opposed to a general `Controlled` operator. [(#5069)](https://github.com/PennyLaneAI/pennylane/pull/5069) From 2329a39dbf50f9d7a0940103d7082b10f16d983a Mon Sep 17 00:00:00 2001 From: Christina Lee Date: Wed, 24 Jan 2024 16:00:21 -0500 Subject: [PATCH 06/19] Update pennylane/transforms/core/transform.py Co-authored-by: Thomas R. Bromley <49409390+trbromley@users.noreply.github.com> --- pennylane/transforms/core/transform.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane/transforms/core/transform.py b/pennylane/transforms/core/transform.py index 72d394b356d..33b532fd555 100644 --- a/pennylane/transforms/core/transform.py +++ b/pennylane/transforms/core/transform.py @@ -198,7 +198,7 @@ def null_postprocessing(results): def expand_fn_transform( expand_fn: Callable[["pennylane.tape.QuantumTape"], "pennylane.tape.QuantumTape"] ) -> "TransformDispatcher": - """Construct a transform from a tape-> tape function. + """Construct a transform from a tape-to-tape function. Args: expand_fn (Callable): a function from a single tape to a single tape From e7b50d39d12818c5776a74aa2f30e0a02bebb958 Mon Sep 17 00:00:00 2001 From: Christina Lee Date: Wed, 24 Jan 2024 16:00:40 -0500 Subject: [PATCH 07/19] Update pennylane/transforms/core/transform.py Co-authored-by: Thomas R. Bromley <49409390+trbromley@users.noreply.github.com> --- pennylane/transforms/core/transform.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pennylane/transforms/core/transform.py b/pennylane/transforms/core/transform.py index 33b532fd555..a4d47ab0132 100644 --- a/pennylane/transforms/core/transform.py +++ b/pennylane/transforms/core/transform.py @@ -212,7 +212,6 @@ def expand_fn_transform( >>> my_transform = qml.transforms.core.expand_fn_transform(device.expand_fn) >>> my_transform - """ @wraps(expand_fn) From e983368926a4de147204af49691110115969c9b3 Mon Sep 17 00:00:00 2001 From: albi3ro Date: Wed, 24 Jan 2024 17:34:30 -0500 Subject: [PATCH 08/19] code coverage, tidy image --- doc/_static/transforms_order.png | Bin 50426 -> 50093 bytes doc/_static/transforms_order.svg | 99 +++++++++--------- .../transforms/core/transform_program.py | 2 +- .../test_transform_program.py | 2 + tests/workflow/test_construct_batch.py | 47 +++++++-- 5 files changed, 92 insertions(+), 58 deletions(-) diff --git a/doc/_static/transforms_order.png b/doc/_static/transforms_order.png index c39f720777825d39e0ecf82e2662887d78723b67..9aee3ea7461b57d48ed67a99ddf894d147d30db3 100644 GIT binary patch literal 50093 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 literal 50426 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 z≫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 diff --git a/doc/_static/transforms_order.svg b/doc/_static/transforms_order.svg index 64d9400a0fb..2fce26d14e4 100644 --- a/doc/_static/transforms_order.svg +++ b/doc/_static/transforms_order.svg @@ -2,9 +2,9 @@ + style="fill:#d0eefe;fill-opacity:1;stroke:#024061;stroke-width:1.09632;stroke-dasharray:none;stroke-opacity:1" + d="M -2.5096944,137.19851 228.91001,138.31866" + id="path10828" + sodipodi:nodetypes="cc" /> Tapes Results Transform 1 + id="tspan1090">Transform 1 Transform 2 + x="-156.4115" + y="62.916519">Transform 2 gradient + x="-151.41635" + y="91.295265">gradient device + x="-149.25452" + y="122.42915">device Final + x="-142.96228" + y="157.56412">Final ML Boundary diff --git a/pennylane/transforms/core/transform_program.py b/pennylane/transforms/core/transform_program.py index cf1e5f6d74b..857cdc3b8ae 100644 --- a/pennylane/transforms/core/transform_program.py +++ b/pennylane/transforms/core/transform_program.py @@ -197,7 +197,7 @@ def __contains__(self, obj): return obj in self._transform_program if isinstance(obj, TransformDispatcher): return any(obj.transform == t.transform for t in self) - raise ValueError(f"Contains not implemented for TransformProgram and object {obj}") + return False def push_back(self, transform_container: TransformContainer): """Add a transform (container) to the end of the program. diff --git a/tests/transforms/test_experimental/test_transform_program.py b/tests/transforms/test_experimental/test_transform_program.py index 63c73d58de1..c928918bc3c 100644 --- a/tests/transforms/test_experimental/test_transform_program.py +++ b/tests/transforms/test_experimental/test_transform_program.py @@ -168,6 +168,8 @@ def test_contains(self): t_not = TransformContainer(transform=qml.compile) assert t_not not in program + assert "a" not in program + def test_add_single_programs(self): """Test adding two transform programs""" transform_program1 = TransformProgram() diff --git a/tests/workflow/test_construct_batch.py b/tests/workflow/test_construct_batch.py index a670c17ca7f..42ae7a8b9ba 100644 --- a/tests/workflow/test_construct_batch.py +++ b/tests/workflow/test_construct_batch.py @@ -49,17 +49,13 @@ def test_transform_program_gradient_fn(self): def circuit(): return qml.expval(qml.PauliZ(0)) - expected_p0 = qml.transforms.core.TransformContainer( - qml.transforms.cancel_inverses.transform - ) - expected_p1 = qml.transforms.core.TransformContainer( + expected_p0 = TransformContainer(qml.transforms.cancel_inverses.transform) + expected_p1 = TransformContainer( qml.transforms.merge_rotations.transform, kwargs={"atol": 1e-5} ) - expected_p2 = qml.transforms.core.TransformContainer( - qml.transforms.compile.transform, kwargs={"num_passes": 2} - ) + expected_p2 = TransformContainer(qml.transforms.compile.transform, kwargs={"num_passes": 2}) - ps_expand_fn = qml.transforms.core.TransformContainer( + ps_expand_fn = TransformContainer( qml.gradients.param_shift.expand_transform, kwargs={"shifts": 2} ) @@ -92,6 +88,18 @@ def circuit(): assert p_sliced[1].transform == qml.devices.preprocess.validate_device_wires.transform assert p_sliced[2].transform == qml.devices.preprocess.decompose.transform + def test_gradient_fn_device_gradient(self): + """Test that if level="gradient" but the gradient does not have preprocessing, the program is strictly user transforms.""" + + @qml.transforms.cancel_inverses + @qml.qnode(qml.device("default.qubit"), diff_method="backprop") + def circuit(): + return qml.state() + + prog = transform_program(circuit, level="gradient") + assert len(prog) == 1 + assert qml.transforms.cancel_inverses in prog + def test_transform_program_device_gradient(self): """Test the trnsform program contents when using a device derivative.""" @@ -362,6 +370,8 @@ def circuit(): assert fn(dummy_res) == expected_res def test_slicing_level(self): + """Test that the level can be a slice.""" + @qml.transforms.merge_rotations @qml.qnode(qml.device("default.qubit")) def circuit(x): @@ -378,3 +388,24 @@ def circuit(x): ) assert qml.equal(batch[0], expected) assert fn(("a",)) == ("a",) + + def test_qfunc_with_shots_arg(self): + """Test that the tape uses device shots only when qfunc has a shots kwarg""" + + dev = qml.device("default.qubit", shots=100) + + @qml.qnode(dev) + def circuit(shots): + for _ in range(shots): + qml.S(0) + return qml.expval(qml.PauliZ(0)) + + assert circuit.qfunc_uses_shots_arg + + batch, fn = construct_batch(circuit, level=None)(shots=2) + assert len(batch) == 1 + expected = qml.tape.QuantumScript( + [qml.S(0), qml.S(0)], [qml.expval(qml.PauliZ(0))], shots=100 + ) + assert qml.equal(batch[0], expected) + assert fn(("a",)) == ("a",) From 21f7f12cfb7ec185b4cef33166c6d23b7a4e483f Mon Sep 17 00:00:00 2001 From: albi3ro Date: Fri, 26 Jan 2024 09:46:57 -0500 Subject: [PATCH 09/19] remove qfunc uses shots arg property, just recalculate --- pennylane/workflow/construct_batch.py | 3 ++- pennylane/workflow/qnode.py | 8 -------- tests/workflow/test_construct_batch.py | 2 -- 3 files changed, 2 insertions(+), 11 deletions(-) diff --git a/pennylane/workflow/construct_batch.py b/pennylane/workflow/construct_batch.py index c332451aeb2..4cd54946bac 100644 --- a/pennylane/workflow/construct_batch.py +++ b/pennylane/workflow/construct_batch.py @@ -14,6 +14,7 @@ """Contains a function extracting the tapes at postprocessing at any stage of a transform program. """ +import inspect from typing import Union, Callable, Tuple import pennylane as qml @@ -253,7 +254,7 @@ def circuit(x): def batch_constructor(*args, **kwargs) -> Tuple[Tuple["qml.tape.QuantumTape", Callable]]: """Create a batch of tapes and a post processing function.""" - if qnode.qfunc_uses_shots_arg: + if "shots" in inspect.signature(qnode.func).parameters: shots = _get_device_shots(qnode.device) else: shots = kwargs.pop("shots", _get_device_shots(qnode.device)) diff --git a/pennylane/workflow/qnode.py b/pennylane/workflow/qnode.py index 149433082ec..c02dcf23192 100644 --- a/pennylane/workflow/qnode.py +++ b/pennylane/workflow/qnode.py @@ -534,14 +534,6 @@ def __repr__(self): self.diff_method, ) - @property - def qfunc_uses_shots_arg(self) -> bool: - """Whether or not the qfunc has a ``shots`` keyword argument. - - If so, shots cannot be dynamically set on a call to a ``QNode``. - """ - return self._qfunc_uses_shots_arg - @property def interface(self): """The interface used by the QNode""" diff --git a/tests/workflow/test_construct_batch.py b/tests/workflow/test_construct_batch.py index 42ae7a8b9ba..f16a3819161 100644 --- a/tests/workflow/test_construct_batch.py +++ b/tests/workflow/test_construct_batch.py @@ -400,8 +400,6 @@ def circuit(shots): qml.S(0) return qml.expval(qml.PauliZ(0)) - assert circuit.qfunc_uses_shots_arg - batch, fn = construct_batch(circuit, level=None)(shots=2) assert len(batch) == 1 expected = qml.tape.QuantumScript( From 952933fb0f6f6c16d9f8b1b286ebe3b4e35a19c0 Mon Sep 17 00:00:00 2001 From: Christina Lee Date: Tue, 30 Jan 2024 13:56:32 -0500 Subject: [PATCH 10/19] Apply suggestions from code review Co-authored-by: Matthew Silverman --- pennylane/workflow/construct_batch.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/pennylane/workflow/construct_batch.py b/pennylane/workflow/construct_batch.py index 4cd54946bac..81c0084914c 100644 --- a/pennylane/workflow/construct_batch.py +++ b/pennylane/workflow/construct_batch.py @@ -169,9 +169,9 @@ def construct_batch(qnode: QNode, level: Union[None, str, int, slice] = "user") Callable: a function with the same call signature as the initial quantum function. This function returns a batch (tuple) of tapes and postprocessing function. - ..seealso:: :func:`pennylane.workflow.transform_program` to inspect the contents of the transform program for a specified level. + .. seealso:: :func:`pennylane.workflow.transform_program` to inspect the contents of the transform program for a specified level. - Suppose we have a device with several user transforms. + Suppose we have a QNode with several user transforms. .. code-block:: python @@ -259,10 +259,7 @@ def batch_constructor(*args, **kwargs) -> Tuple[Tuple["qml.tape.QuantumTape", Ca else: shots = kwargs.pop("shots", _get_device_shots(qnode.device)) - with qml.queuing.AnnotatedQueue() as q: - qnode.func(*args, **kwargs) - - initial_tape = qml.tape.QuantumScript.from_queue(q, shots) + initial_tape = qml.tape.make_qscript(qnode.func, shots=shots)(*args, **kwargs) return program((initial_tape,)) return batch_constructor From a8a99da52d1a6ea021659ee46943a99269039e24 Mon Sep 17 00:00:00 2001 From: albi3ro Date: Tue, 30 Jan 2024 14:17:44 -0500 Subject: [PATCH 11/19] update capitalization on image --- doc/_static/transforms_order.png | Bin 50093 -> 50017 bytes doc/_static/transforms_order.svg | 26 +++++++++++++------------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/doc/_static/transforms_order.png b/doc/_static/transforms_order.png index 9aee3ea7461b57d48ed67a99ddf894d147d30db3..e7c026865ed420599bd0ca1b51f89d57b8547cf6 100644 GIT binary patch literal 50017 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 diff --git a/doc/_static/transforms_order.svg b/doc/_static/transforms_order.svg index 2fce26d14e4..09197228d00 100644 --- a/doc/_static/transforms_order.svg +++ b/doc/_static/transforms_order.svg @@ -28,12 +28,12 @@ inkscape:document-units="mm" showgrid="false" inkscape:zoom="1" - inkscape:cx="449.5" - inkscape:cy="179.5" - inkscape:window-width="1652" + inkscape:cx="324.5" + inkscape:cy="233.5" + inkscape:window-width="1790" inkscape:window-height="847" - inkscape:window-x="105" - inkscape:window-y="62" + inkscape:window-x="1471" + inkscape:window-y="26" inkscape:window-maximized="0" inkscape:current-layer="layer1" /> Tapes + y="91.21228">tapes Results + y="185.7616">results Transform 1 + id="tspan501">transform 1 Transform 2 + y="62.916519">transform 2 Final + y="157.56412">final ML Boundary + y="200.38033">ML boundary Date: Tue, 30 Jan 2024 14:30:36 -0500 Subject: [PATCH 12/19] responding to feedback and fixing up documentation --- doc/releases/changelog-dev.md | 2 +- pennylane/devices/default_qubit.py | 2 +- pennylane/transforms/core/transform.py | 8 ++--- pennylane/workflow/__init__.py | 4 +-- pennylane/workflow/construct_batch.py | 34 ++++++++++----------- tests/workflow/test_construct_batch.py | 42 +++++++++++++------------- 6 files changed, 45 insertions(+), 47 deletions(-) diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md index ba8f448611c..e022188128c 100644 --- a/doc/releases/changelog-dev.md +++ b/doc/releases/changelog-dev.md @@ -116,7 +116,7 @@ * Raise a more informative error when calling `adjoint_jacobian` with trainable state-prep operations. [(#5026)](https://github.com/PennyLaneAI/pennylane/pull/5026) -* Adds `qml.workflow.transform_program` and `qml.workflow.construct_batch` to inspect the transform program and batch of tapes +* Adds `qml.workflow.get_transform_program` and `qml.workflow.construct_batch` to inspect the transform program and batch of tapes at different stages. [(#5084)](https://github.com/PennyLaneAI/pennylane/pull/5084) diff --git a/pennylane/devices/default_qubit.py b/pennylane/devices/default_qubit.py index 6f5ea905bb3..ade6ec28344 100644 --- a/pennylane/devices/default_qubit.py +++ b/pennylane/devices/default_qubit.py @@ -161,7 +161,7 @@ def adjoint_state_measurements( def adjoint_ops(op: qml.operation.Operator) -> bool: """Specify whether or not an Operator is supported by adjoint differentiation.""" - return op.num_params == 0 or op.num_params == 1 and op.has_generator + return op.num_params == 0 or (op.num_params == 1 and op.has_generator) def adjoint_observables(obs: qml.operation.Operator) -> bool: diff --git a/pennylane/transforms/core/transform.py b/pennylane/transforms/core/transform.py index a4d47ab0132..303cef31025 100644 --- a/pennylane/transforms/core/transform.py +++ b/pennylane/transforms/core/transform.py @@ -195,9 +195,7 @@ def null_postprocessing(results): return results[0] -def expand_fn_transform( - expand_fn: Callable[["pennylane.tape.QuantumTape"], "pennylane.tape.QuantumTape"] -) -> "TransformDispatcher": +def expand_fn_transform(expand_fn: Callable) -> "TransformDispatcher": """Construct a transform from a tape-to-tape function. Args: @@ -215,7 +213,7 @@ def expand_fn_transform( """ @wraps(expand_fn) - def wrapped_expand_fn(tape): - return (expand_fn(tape),), null_postprocessing + def wrapped_expand_fn(tape, *args, **kwargs): + return (expand_fn(tape, *args, **kwargs),), null_postprocessing return transform(wrapped_expand_fn) diff --git a/pennylane/workflow/__init__.py b/pennylane/workflow/__init__.py index eb7a66f3581..b859a2e5ba0 100644 --- a/pennylane/workflow/__init__.py +++ b/pennylane/workflow/__init__.py @@ -26,7 +26,7 @@ ~workflow.cache_execute ~workflow.set_shots ~workflow.construct_batch - ~workflow.transform_program + ~workflow.get_transform_program Supported interfaces ~~~~~~~~~~~~~~~~~~~~ @@ -57,4 +57,4 @@ from .set_shots import set_shots from .execution import execute, cache_execute, SUPPORTED_INTERFACES, INTERFACE_MAP from .qnode import QNode, qnode -from .construct_batch import construct_batch, transform_program +from .construct_batch import construct_batch, get_transform_program diff --git a/pennylane/workflow/construct_batch.py b/pennylane/workflow/construct_batch.py index 81c0084914c..f78212c8113 100644 --- a/pennylane/workflow/construct_batch.py +++ b/pennylane/workflow/construct_batch.py @@ -36,20 +36,20 @@ def _get_full_transform_program(qnode: QNode) -> "qml.transforms.core.TransformP return program -def transform_program(qnode: "QNode", level=None) -> "qml.transforms.core.TransformProgram": +def get_transform_program(qnode: "QNode", level=None) -> "qml.transforms.core.TransformProgram": """Extract a transform program at a designated level. Args: qnode (QNode): the qnode to get the transform program for. - level (None, str, int, slice): And indication + level (None, str, int, slice): And indication of what transforms to use from the full program. * ``None``: use the full transform program - * ``str``: Acceptable keys are ``"user"``, ``"device"``, and ``"gradient"`` + * ``str``: Acceptable keys are ``"user"``, ``"device"``, ``"top"`` and ``"gradient"`` * ``int``: How many transforms to include, starting from the front of the program * ``slice``: a slice to select out components of the transform program. Returns: - TransformProrgram: the transform program corresponding to t + TransformProrgram: the transform program corresponding to the requested level. The transforms are organized as: @@ -76,7 +76,7 @@ def circuit(): By default, we get the full transform program. This can be manaully specified by ``level=None``. - >>> qml.workflow.transform_program(circuit) + >>> qml.workflow.get_transform_program(circuit) TransformProgram(compile, _expand_metric_tensor, _expand_transform_param_shift, validate_device_wires, defer_measurements, decompose, validate_measurements, validate_observables, metric_tensor) @@ -84,43 +84,43 @@ def circuit(): The ``"user"`` transforms are the ones manually applied to the qnode, :class:`~.cancel_inverses` and :class:`~.merge_rotations`. - >>> qml.workflow.transform_program(circuit, level="user") + >>> qml.workflow.get_transform_program(circuit, level="user") TransformProgram(cancel_inverses, merge_rotations) The ``_expand_transform_param_shift`` is the ``"gradient"`` transform. This expands all trainable operations to a state where the parameter shift transform can operate on them. For example, it will decompose any parametrized templates into operators that have generators. - >>> qml.workflow.transform_program(circuit, level="gradient") + >>> qml.workflow.get_transform_program(circuit, level="gradient") TransformProgram(cancel_inverses, merge_rotations, _expand_transform_param_shift) ``"device"`` includes all transforms except for a ``"final"`` transform, if it exists. This usually corresponds to the circuits that will be sent to the device to execute. - >>> qml.workflow.transform_program(circuit, level="device") + >>> qml.workflow.get_transform_program(circuit, level="device") TransformProgram(cancel_inverses, merge_rotations, _expand_transform_param_shift, validate_device_wires, defer_measurements, decompose, validate_measurements, validate_observables) ``"top"`` and ``0`` both return empty transform programs. - >>> qml.workflow.transform_program(circuit, level="top") + >>> qml.workflow.get_transform_program(circuit, level="top") TransformProgram() - >>> qml.workflow.transform_program(circuit, level=0) + >>> qml.workflow.get_transform_program(circuit, level=0) TransformProgram() The ``level`` can also be any integer, corresponding to a number of transforms in the program. - >>> qml.workflow.transform_program(circuit, level=2) + >>> qml.workflow.get_transform_program(circuit, level=2) TransformProgram(cancel_inverses, merge_rotations) ``level`` can also accept a ``slice`` object to select out any arbitrary subset of the transform program. This allows you to select different starting transforms or strides. For example, you can skip the first transform or reverse the order: - >>> qml.workflow.transform_program(circuit, level=slice(1,3)) + >>> qml.workflow.get_transform_program(circuit, level=slice(1,3)) TransformProgram(merge_rotations, _expand_transform_param_shift) - >>> qml.workflow.transform_program(circuit, level=slice(None, None, -1)) + >>> qml.workflow.get_transform_program(circuit, level=slice(None, None, -1)) TransformProgram(metric_tensor, validate_observables, validate_measurements, decompose, defer_measurements, validate_device_wires, _expand_transform_param_shift, _expand_metric_tensor, merge_rotations, cancel_inverses) @@ -158,7 +158,7 @@ def construct_batch(qnode: QNode, level: Union[None, str, int, slice] = "user") Args: qnode (QNode): the qnode we want to get the tapes and post-processing for. - level (None, str, int, slice): And indication + level (None, str, int, slice): And indication of what transforms to use from the full program. * ``None``: use the full transform program * ``str``: Acceptable keys are ``"top"``, ``"user"``, ``"device"``, and ``"gradient"`` @@ -167,9 +167,9 @@ def construct_batch(qnode: QNode, level: Union[None, str, int, slice] = "user") Returns: Callable: a function with the same call signature as the initial quantum function. This function returns - a batch (tuple) of tapes and postprocessing function. + a batch (tuple) of tapes and postprocessing function. - .. seealso:: :func:`pennylane.workflow.transform_program` to inspect the contents of the transform program for a specified level. + .. seealso:: :func:`pennylane.workflow.get_transform_program` to inspect the contents of the transform program for a specified level. Suppose we have a QNode with several user transforms. @@ -250,7 +250,7 @@ def circuit(x): + (1) [Y0])] """ - program = transform_program(qnode, level=level) + program = get_transform_program(qnode, level=level) def batch_constructor(*args, **kwargs) -> Tuple[Tuple["qml.tape.QuantumTape", Callable]]: """Create a batch of tapes and a post processing function.""" diff --git a/tests/workflow/test_construct_batch.py b/tests/workflow/test_construct_batch.py index f16a3819161..88abaa66662 100644 --- a/tests/workflow/test_construct_batch.py +++ b/tests/workflow/test_construct_batch.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. """ -Contains tests for the `qml.workflow.transform_program` getter. +Contains tests for the `qml.workflow.get_transform_program` getter and `construct_batch`. """ from functools import partial @@ -23,7 +23,7 @@ import pennylane as qml from pennylane.transforms.core.transform_dispatcher import TransformContainer from pennylane.transforms.core.transform_program import TransformProgram -from pennylane.workflow import transform_program, construct_batch +from pennylane.workflow import get_transform_program, construct_batch class TestTransformProgramGetter: @@ -35,9 +35,9 @@ def circuit(): return qml.state() with pytest.raises(ValueError, match=r"level bah not recognized."): - transform_program(circuit, level="bah") + get_transform_program(circuit, level="bah") - def test_transform_program_gradient_fn(self): + def test_get_transform_program_gradient_fn_transform(self): """Tests for the transform program when the gradient_fn is a transform.""" dev = qml.device("default.qubit", wires=4) @@ -59,30 +59,30 @@ def circuit(): qml.gradients.param_shift.expand_transform, kwargs={"shifts": 2} ) - p0 = transform_program(circuit, level=0) + p0 = get_transform_program(circuit, level=0) assert isinstance(p0, TransformProgram) assert len(p0) == 0 - p0 = transform_program(circuit, level="top") + p0 = get_transform_program(circuit, level="top") assert isinstance(p0, TransformProgram) assert len(p0) == 0 - p_grad = transform_program(circuit, level="gradient") + p_grad = get_transform_program(circuit, level="gradient") assert isinstance(p_grad, TransformProgram) assert len(p_grad) == 4 assert p_grad == TransformProgram([expected_p0, expected_p1, expected_p2, ps_expand_fn]) - p_dev = transform_program(circuit, level="device") + p_dev = get_transform_program(circuit, level="device") assert isinstance(p_grad, TransformProgram) - p_default = transform_program(circuit) - p_none = transform_program(circuit, None) + p_default = get_transform_program(circuit) + p_none = get_transform_program(circuit, None) assert p_dev == p_default assert p_none == p_dev assert len(p_dev) == 9 assert p_dev == p_grad + dev.preprocess()[0] # slicing - p_sliced = transform_program(circuit, slice(2, 7, 2)) + p_sliced = get_transform_program(circuit, slice(2, 7, 2)) assert len(p_sliced) == 3 assert p_sliced[0].transform == qml.compile.transform assert p_sliced[1].transform == qml.devices.preprocess.validate_device_wires.transform @@ -96,11 +96,11 @@ def test_gradient_fn_device_gradient(self): def circuit(): return qml.state() - prog = transform_program(circuit, level="gradient") + prog = get_transform_program(circuit, level="gradient") assert len(prog) == 1 assert qml.transforms.cancel_inverses in prog - def test_transform_program_device_gradient(self): + def test_get_transform_program_device_gradient(self): """Test the trnsform program contents when using a device derivative.""" dev = qml.device("default.qubit") @@ -111,7 +111,7 @@ def circuit(x): qml.RX(x, 0) return qml.expval(qml.PauliZ(0)) - full_prog = transform_program(circuit) + full_prog = get_transform_program(circuit) assert len(full_prog) == 13 config = qml.devices.ExecutionConfig( @@ -124,7 +124,7 @@ def circuit(x): expected += dev_program assert full_prog == expected - def test_transform_program_legacy_device_interface(self): + def test_get_transform_program_legacy_device_interface(self): """Test the contents of the transform program with the legacy device interface.""" dev = qml.device("default.qubit.legacy", wires=5) @@ -135,7 +135,7 @@ def circuit(x): qml.RX(x, wires=0) return qml.expval(qml.PauliZ(0)) - program = transform_program(circuit) + program = get_transform_program(circuit) m1 = TransformContainer(qml.transforms.merge_rotations.transform) m2 = TransformContainer(dev.batch_transform) @@ -145,7 +145,7 @@ def circuit(x): # this is the best proxy I can find assert program[2].transform.__wrapped__ == dev.expand_fn - def test_transform_program_final_transform(self): + def test_get_transform_program_final_transform(self): """Test that gradient preprocessing and device transform occur before a final transform.""" @qml.metric_tensor @@ -155,22 +155,22 @@ def circuit(): qml.IsingXX(1.234, wires=(0, 1)) return qml.expval(qml.PauliZ(0)), qml.expval(qml.PauliX(0)) - user_program = transform_program(circuit, level="user") + user_program = get_transform_program(circuit, level="user") assert len(user_program) == 2 assert user_program[0].transform == qml.compile.transform assert user_program[1].transform == qml.metric_tensor.expand_transform - grad_program = transform_program(circuit, level="gradient") + grad_program = get_transform_program(circuit, level="gradient") assert len(grad_program) == 3 assert grad_program[0].transform == qml.compile.transform assert grad_program[1].transform == qml.metric_tensor.expand_transform assert grad_program[2].transform == qml.gradients.param_shift.expand_transform - dev_program = transform_program(circuit, level="device") + dev_program = get_transform_program(circuit, level="device") assert len(dev_program) == 3 + len(circuit.device.preprocess()[0]) # currently 8 assert qml.metric_tensor not in dev_program - full = transform_program(circuit) + full = get_transform_program(circuit) assert full[-1].transform == qml.metric_tensor.transform From d00ac60835ce68e4707191ff4b101b03efc79b2f Mon Sep 17 00:00:00 2001 From: albi3ro Date: Tue, 30 Jan 2024 16:33:22 -0500 Subject: [PATCH 13/19] minor documentation fix and test addition --- pennylane/workflow/construct_batch.py | 8 ++++---- .../test_experimental/test_transform_dispatcher.py | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pennylane/workflow/construct_batch.py b/pennylane/workflow/construct_batch.py index f78212c8113..73f9b7d115c 100644 --- a/pennylane/workflow/construct_batch.py +++ b/pennylane/workflow/construct_batch.py @@ -77,9 +77,9 @@ def circuit(): By default, we get the full transform program. This can be manaully specified by ``level=None``. >>> qml.workflow.get_transform_program(circuit) - TransformProgram(compile, _expand_metric_tensor, _expand_transform_param_shift, - validate_device_wires, defer_measurements, decompose, validate_measurements, - validate_observables, metric_tensor) + TransformProgram(cancel_inverses, merge_rotations, _expand_metric_tensor, + _expand_transform_param_shift, validate_device_wires, defer_measurements, + decompose, validate_measurements, validate_observables, metric_tensor) The ``"user"`` transforms are the ones manually applied to the qnode, :class:`~.cancel_inverses` and :class:`~.merge_rotations`. @@ -178,7 +178,7 @@ def construct_batch(qnode: QNode, level: Union[None, str, int, slice] = "user") @qml.transforms.undo_swaps @qml.transforms.merge_rotations @qml.transforms.cancel_inverses - @qml.qnode(dev, diff_method="parameter-shift", shifts=np.pi / 4) + @qml.qnode(qml.device('default.qubit'), diff_method="parameter-shift", shifts=np.pi / 4) def circuit(x): qml.RandomLayers(qml.numpy.array([[1.0, 2.0]]), wires=(0,1)) qml.RX(x, wires=0) diff --git a/tests/transforms/test_experimental/test_transform_dispatcher.py b/tests/transforms/test_experimental/test_transform_dispatcher.py index 7e103d57864..9305e2e1b9d 100644 --- a/tests/transforms/test_experimental/test_transform_dispatcher.py +++ b/tests/transforms/test_experimental/test_transform_dispatcher.py @@ -637,10 +637,10 @@ def custom_transform( # pylint:disable=unused-variable def test_expand_fn_transform(): """Tests the expand_fn_transform.""" - def my_expand_fn(tape): + def my_expand_fn(tape, op1, op2=qml.S(0), op3=qml.S(0)): """my docstring.""" return qml.tape.QuantumScript( - tape.operations + [qml.PauliX(0)], tape.measurements, tape.shots + tape.operations + [op1, op2, op3], tape.measurements, tape.shots ) t = qml.transforms.core.expand_fn_transform(my_expand_fn) @@ -648,10 +648,10 @@ def my_expand_fn(tape): assert isinstance(t, TransformDispatcher) tape = qml.tape.QuantumScript([qml.S(0)], [qml.expval(qml.PauliZ(0))], shots=50) - batch, fn = t(tape) + batch, fn = t(tape, qml.PauliX(0), op3=qml.T(0)) assert len(batch) == 1 expected = qml.tape.QuantumScript( - [qml.S(0), qml.PauliX(0)], [qml.expval(qml.PauliZ(0))], shots=50 + [qml.S(0), qml.PauliX(0), qml.S(0), qml.T(0)], [qml.expval(qml.PauliZ(0))], shots=50 ) assert qml.equal(batch[0], expected) assert fn(("a",)) == "a" From c0f7c364c400569bd54f4e9c2175e5c991d480d8 Mon Sep 17 00:00:00 2001 From: albi3ro Date: Wed, 31 Jan 2024 09:27:34 -0500 Subject: [PATCH 14/19] move expand_fn_transform --- pennylane/transforms/core/transform.py | 32 +------------------ pennylane/workflow/construct_batch.py | 32 ++++++++++++++++++- .../test_transform_dispatcher.py | 27 ---------------- tests/workflow/test_construct_batch.py | 27 ++++++++++++++++ 4 files changed, 59 insertions(+), 59 deletions(-) diff --git a/pennylane/transforms/core/transform.py b/pennylane/transforms/core/transform.py index 303cef31025..d464561cdc9 100644 --- a/pennylane/transforms/core/transform.py +++ b/pennylane/transforms/core/transform.py @@ -15,8 +15,7 @@ This module contains the transform function/decorator to make your custom transforms compatible with tapes, quantum functions and QNodes. """ -from functools import wraps -from typing import get_type_hints, Callable +from typing import get_type_hints from .transform_dispatcher import TransformDispatcher, TransformError @@ -188,32 +187,3 @@ def qnode_circuit(a): is_informative=is_informative, final_transform=final_transform, ) - - -def null_postprocessing(results): - """A postprocessing function with null behavior.""" - return results[0] - - -def expand_fn_transform(expand_fn: Callable) -> "TransformDispatcher": - """Construct a transform from a tape-to-tape function. - - Args: - expand_fn (Callable): a function from a single tape to a single tape - - Returns: - - .TransformDispatcher: Returns a transform dispatcher object that that can transform any - circuit-like object in PennyLane. - - >>> device = qml.device('default.qubit.legacy', wires=2) - >>> my_transform = qml.transforms.core.expand_fn_transform(device.expand_fn) - >>> my_transform - - """ - - @wraps(expand_fn) - def wrapped_expand_fn(tape, *args, **kwargs): - return (expand_fn(tape, *args, **kwargs),), null_postprocessing - - return transform(wrapped_expand_fn) diff --git a/pennylane/workflow/construct_batch.py b/pennylane/workflow/construct_batch.py index 73f9b7d115c..b8659fd54f7 100644 --- a/pennylane/workflow/construct_batch.py +++ b/pennylane/workflow/construct_batch.py @@ -14,6 +14,7 @@ """Contains a function extracting the tapes at postprocessing at any stage of a transform program. """ +from functools import wraps import inspect from typing import Union, Callable, Tuple @@ -21,6 +22,35 @@ from .qnode import QNode, _make_execution_config, _get_device_shots +def null_postprocessing(results): + """A postprocessing function with null behavior.""" + return results[0] + + +def expand_fn_transform(expand_fn: Callable) -> "qml.transforms.core.TransformDispatcher": + """Construct a transform from a tape-to-tape function. + + Args: + expand_fn (Callable): a function from a single tape to a single tape + + Returns: + + .TransformDispatcher: Returns a transform dispatcher object that that can transform any + circuit-like object in PennyLane. + + >>> device = qml.device('default.qubit.legacy', wires=2) + >>> my_transform = qml.transforms.core.expand_fn_transform(device.expand_fn) + >>> my_transform + + """ + + @wraps(expand_fn) + def wrapped_expand_fn(tape, *args, **kwargs): + return (expand_fn(tape, *args, **kwargs),), null_postprocessing + + return qml.transform(wrapped_expand_fn) + + def _get_full_transform_program(qnode: QNode) -> "qml.transforms.core.TransformProgram": program = qml.transforms.core.TransformProgram(qnode.transform_program) if getattr(qnode.gradient_fn, "expand_transform", False): @@ -32,7 +62,7 @@ def _get_full_transform_program(qnode: QNode) -> "qml.transforms.core.TransformP config = _make_execution_config(qnode) return program + qnode.device.preprocess(config)[0] program.add_transform(qml.transform(qnode.device.batch_transform)) - program.add_transform(qml.transforms.core.expand_fn_transform(qnode.device.expand_fn)) + program.add_transform(expand_fn_transform(qnode.device.expand_fn)) return program diff --git a/tests/transforms/test_experimental/test_transform_dispatcher.py b/tests/transforms/test_experimental/test_transform_dispatcher.py index 9305e2e1b9d..b1ef83bb65c 100644 --- a/tests/transforms/test_experimental/test_transform_dispatcher.py +++ b/tests/transforms/test_experimental/test_transform_dispatcher.py @@ -18,7 +18,6 @@ import pytest import pennylane as qml from pennylane.transforms.core import transform, TransformError, TransformContainer -from pennylane.transforms.core.transform_dispatcher import TransformDispatcher dev = qml.device("default.qubit", wires=2) @@ -632,29 +631,3 @@ def custom_transform( # pylint:disable=unused-variable tape = tape.copy() tape._ops.pop(index) # pylint:disable=protected-access return [tape], lambda x: x - - -def test_expand_fn_transform(): - """Tests the expand_fn_transform.""" - - def my_expand_fn(tape, op1, op2=qml.S(0), op3=qml.S(0)): - """my docstring.""" - return qml.tape.QuantumScript( - tape.operations + [op1, op2, op3], tape.measurements, tape.shots - ) - - t = qml.transforms.core.expand_fn_transform(my_expand_fn) - - assert isinstance(t, TransformDispatcher) - tape = qml.tape.QuantumScript([qml.S(0)], [qml.expval(qml.PauliZ(0))], shots=50) - - batch, fn = t(tape, qml.PauliX(0), op3=qml.T(0)) - assert len(batch) == 1 - expected = qml.tape.QuantumScript( - [qml.S(0), qml.PauliX(0), qml.S(0), qml.T(0)], [qml.expval(qml.PauliZ(0))], shots=50 - ) - assert qml.equal(batch[0], expected) - assert fn(("a",)) == "a" - - assert repr(t) == "" - assert t.__doc__ == "my docstring." diff --git a/tests/workflow/test_construct_batch.py b/tests/workflow/test_construct_batch.py index 88abaa66662..bc6113d5b41 100644 --- a/tests/workflow/test_construct_batch.py +++ b/tests/workflow/test_construct_batch.py @@ -24,6 +24,33 @@ from pennylane.transforms.core.transform_dispatcher import TransformContainer from pennylane.transforms.core.transform_program import TransformProgram from pennylane.workflow import get_transform_program, construct_batch +from pennylane.workflow.construct_batch import expand_fn_transform + + +def test_expand_fn_transform(): + """Tests the expand_fn_transform.""" + + def my_expand_fn(tape, op1, op2=qml.S(0), op3=qml.S(0)): + """my docstring.""" + return qml.tape.QuantumScript( + tape.operations + [op1, op2, op3], tape.measurements, tape.shots + ) + + t = expand_fn_transform(my_expand_fn) + + assert isinstance(t, qml.transforms.core.TransformDispatcher) + tape = qml.tape.QuantumScript([qml.S(0)], [qml.expval(qml.PauliZ(0))], shots=50) + + batch, fn = t(tape, qml.PauliX(0), op3=qml.T(0)) + assert len(batch) == 1 + expected = qml.tape.QuantumScript( + [qml.S(0), qml.PauliX(0), qml.S(0), qml.T(0)], [qml.expval(qml.PauliZ(0))], shots=50 + ) + assert qml.equal(batch[0], expected) + assert fn(("a",)) == "a" + + assert repr(t) == "" + assert t.__doc__ == "my docstring." class TestTransformProgramGetter: From dc1e95decc97a1a7af068a5d4b3fce1f1c0664aa Mon Sep 17 00:00:00 2001 From: albi3ro Date: Wed, 31 Jan 2024 09:32:23 -0500 Subject: [PATCH 15/19] fix import --- pennylane/transforms/core/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane/transforms/core/__init__.py b/pennylane/transforms/core/__init__.py index bcddcbf5d98..ff2b97cc900 100644 --- a/pennylane/transforms/core/__init__.py +++ b/pennylane/transforms/core/__init__.py @@ -14,6 +14,6 @@ r"""This module contains the experimental transforms building blocks (core). """ -from .transform import transform, expand_fn_transform +from .transform import transform from .transform_dispatcher import TransformDispatcher, TransformContainer, TransformError from .transform_program import TransformProgram From 39b78aa72629d834dfbdccf2d1fef3ad911d7085 Mon Sep 17 00:00:00 2001 From: albi3ro Date: Wed, 31 Jan 2024 10:48:56 -0500 Subject: [PATCH 16/19] set seed in flaky test --- tests/devices/default_qubit/test_default_qubit.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/devices/default_qubit/test_default_qubit.py b/tests/devices/default_qubit/test_default_qubit.py index d98a20954ea..35a76028f42 100644 --- a/tests/devices/default_qubit/test_default_qubit.py +++ b/tests/devices/default_qubit/test_default_qubit.py @@ -1725,6 +1725,8 @@ def test_postselection_valid_finite_shots( if use_jit and (interface != "jax" or isinstance(shots, tuple)): pytest.skip("Cannot JIT in non-JAX interfaces, or with shot vectors.") + np.random.seed(42) + dev = qml.device("default.qubit") param = qml.math.asarray(param, like=interface) From 5aee0203485b8c88e86a5cbc4201a9b71b86b644 Mon Sep 17 00:00:00 2001 From: Christina Lee Date: Wed, 31 Jan 2024 10:59:45 -0500 Subject: [PATCH 17/19] Apply suggestions from code review Co-authored-by: Thomas R. Bromley <49409390+trbromley@users.noreply.github.com> --- doc/releases/changelog-dev.md | 3 --- pennylane/workflow/construct_batch.py | 6 +++--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md index 76af94b613b..abc3a1a5a2d 100644 --- a/doc/releases/changelog-dev.md +++ b/doc/releases/changelog-dev.md @@ -143,9 +143,6 @@ at different stages. [(#5084)](https://github.com/PennyLaneAI/pennylane/pull/5084) -* Adds a `qml.transforms.core.expand_fn_transform` that converts a tape-to-tape function into a transform. - [(#5084)](https://github.com/PennyLaneAI/pennylane/pull/5084) - * `CRX`, `CRY`, `CRZ`, `CROT`, and `ControlledPhaseShift` (i.e. `CPhaseShift`) now inherit from `ControlledOp`, giving them additional properties such as `control_wire` and `control_values`. Calling `qml.ctrl` on `RX`, `RY`, `RZ`, `Rot`, and `PhaseShift` with a single control wire will return gates of types `CRX`, `CRY`, etc. as opposed to a general `Controlled` operator. [(#5069)](https://github.com/PennyLaneAI/pennylane/pull/5069) diff --git a/pennylane/workflow/construct_batch.py b/pennylane/workflow/construct_batch.py index b8659fd54f7..beb119c1eb2 100644 --- a/pennylane/workflow/construct_batch.py +++ b/pennylane/workflow/construct_batch.py @@ -79,7 +79,7 @@ def get_transform_program(qnode: "QNode", level=None) -> "qml.transforms.core.Tr * ``slice``: a slice to select out components of the transform program. Returns: - TransformProrgram: the transform program corresponding to the requested level. + TransformProgram: the transform program corresponding to the requested level. The transforms are organized as: @@ -104,7 +104,7 @@ def get_transform_program(qnode: "QNode", level=None) -> "qml.transforms.core.Tr def circuit(): return qml.expval(qml.PauliZ(0)) - By default, we get the full transform program. This can be manaully specified by ``level=None``. + By default, we get the full transform program. This can be manually specified by ``level=None``. >>> qml.workflow.get_transform_program(circuit) TransformProgram(cancel_inverses, merge_rotations, _expand_metric_tensor, @@ -242,7 +242,7 @@ def circuit(x): expval( (1) [X0] + (1) [Y0])] - We can inpsect what was directly captured from the qfunc with ``level=0``. + We can inspect what was directly captured from the qfunc with ``level=0``. >>> batch, fn = construct_batch(circuit, level=0)(1.23) >>> batch[0].circuit From a74de9817328f4466e0a03fd942c557cc183426d Mon Sep 17 00:00:00 2001 From: albi3ro Date: Wed, 31 Jan 2024 11:04:20 -0500 Subject: [PATCH 18/19] create keyword args section and usage details --- pennylane/transforms/core/transform.py | 7 +- pennylane/workflow/construct_batch.py | 266 +++++++++++++------------ 2 files changed, 140 insertions(+), 133 deletions(-) diff --git a/pennylane/transforms/core/transform.py b/pennylane/transforms/core/transform.py index d464561cdc9..f2ec5d8d08c 100644 --- a/pennylane/transforms/core/transform.py +++ b/pennylane/transforms/core/transform.py @@ -45,14 +45,15 @@ def transform( * The transform must have the following structure (type hinting is optional): ``my_quantum_transform(tape: qml.tape.QuantumTape, ...) -> ( Sequence[qml.tape.QuantumTape], Callable)`` - expand_transform (Callable): An optional expand transform is applied directly before the input + Keyword Args: + expand_transform=None (Optional[Callable]): An optional expand transform is applied directly before the input quantum transform. It must be a function that satisfies the same requirements as ``quantum_transform``. - classical_cotransform (Callable): A classical co-transform is a function to post-process the classical + classical_cotransform=None (Optional[Callable]): A classical co-transform is a function to post-process the classical jacobian and the quantum jacobian and has the signature: ``my_cotransform(qjac, cjac, tape) -> tensor_like`` is_informative=False (bool): Whether or not a transform is informative. If true the transform is queued at the end of the transform program and the tapes or qnode aren't executed. - final_transform (bool): Whether or not the transform is terminal. If true the transform is queued at the end + final_transform=False (bool): Whether or not the transform is terminal. If true the transform is queued at the end of the transform program. ``is_informative`` supersedes ``final_transform``. Returns: diff --git a/pennylane/workflow/construct_batch.py b/pennylane/workflow/construct_batch.py index beb119c1eb2..4a5f0d5066c 100644 --- a/pennylane/workflow/construct_batch.py +++ b/pennylane/workflow/construct_batch.py @@ -81,79 +81,81 @@ def get_transform_program(qnode: "QNode", level=None) -> "qml.transforms.core.Tr Returns: TransformProgram: the transform program corresponding to the requested level. + .. details:: + :title: Usage Details - The transforms are organized as: + The transforms are organized as: - .. image:: ../../_static/transforms_order.png - :align: center - :width: 800px - :target: javascript:void(0); + .. image:: ../../_static/transforms_order.png + :align: center + :width: 800px + :target: javascript:void(0); - where ``transform1`` is first applied to the ``QNode`` followed by ``transform2``. First user transforms are run on the tapes, - followed by the gradient expansion, followed by the device expansion. "Final" transforms, like ``param_shift`` and ``metric_tensor``, - always occur at the end of the program. + where ``transform1`` is first applied to the ``QNode`` followed by ``transform2``. First user transforms are run on the tapes, + followed by the gradient expansion, followed by the device expansion. "Final" transforms, like ``param_shift`` and ``metric_tensor``, + always occur at the end of the program. - .. code-block:: python + .. code-block:: python - dev = qml.device('default.qubit') + dev = qml.device('default.qubit') - @qml.metric_tensor # final transform - @qml.transforms.merge_rotations # transform 2 - @qml.transforms.cancel_inverses # transform 1 - @qml.qnode(dev, diff_method="parameter-shift", shifts=np.pi / 4) - def circuit(): - return qml.expval(qml.PauliZ(0)) + @qml.metric_tensor # final transform + @qml.transforms.merge_rotations # transform 2 + @qml.transforms.cancel_inverses # transform 1 + @qml.qnode(dev, diff_method="parameter-shift", shifts=np.pi / 4) + def circuit(): + return qml.expval(qml.PauliZ(0)) - By default, we get the full transform program. This can be manually specified by ``level=None``. + By default, we get the full transform program. This can be manually specified by ``level=None``. - >>> qml.workflow.get_transform_program(circuit) - TransformProgram(cancel_inverses, merge_rotations, _expand_metric_tensor, - _expand_transform_param_shift, validate_device_wires, defer_measurements, - decompose, validate_measurements, validate_observables, metric_tensor) + >>> qml.workflow.get_transform_program(circuit) + TransformProgram(cancel_inverses, merge_rotations, _expand_metric_tensor, + _expand_transform_param_shift, validate_device_wires, defer_measurements, + decompose, validate_measurements, validate_observables, metric_tensor) - The ``"user"`` transforms are the ones manually applied to the qnode, :class:`~.cancel_inverses` and - :class:`~.merge_rotations`. + The ``"user"`` transforms are the ones manually applied to the qnode, :class:`~.cancel_inverses` and + :class:`~.merge_rotations`. - >>> qml.workflow.get_transform_program(circuit, level="user") - TransformProgram(cancel_inverses, merge_rotations) + >>> qml.workflow.get_transform_program(circuit, level="user") + TransformProgram(cancel_inverses, merge_rotations) - The ``_expand_transform_param_shift`` is the ``"gradient"`` transform. This expands all trainable - operations to a state where the parameter shift transform can operate on them. For example, it will decompose - any parametrized templates into operators that have generators. + The ``_expand_transform_param_shift`` is the ``"gradient"`` transform. This expands all trainable + operations to a state where the parameter shift transform can operate on them. For example, it will decompose + any parametrized templates into operators that have generators. - >>> qml.workflow.get_transform_program(circuit, level="gradient") - TransformProgram(cancel_inverses, merge_rotations, _expand_transform_param_shift) + >>> qml.workflow.get_transform_program(circuit, level="gradient") + TransformProgram(cancel_inverses, merge_rotations, _expand_transform_param_shift) - ``"device"`` includes all transforms except for a ``"final"`` transform, if it exists. This usually - corresponds to the circuits that will be sent to the device to execute. + ``"device"`` includes all transforms except for a ``"final"`` transform, if it exists. This usually + corresponds to the circuits that will be sent to the device to execute. - >>> qml.workflow.get_transform_program(circuit, level="device") - TransformProgram(cancel_inverses, merge_rotations, _expand_transform_param_shift, - validate_device_wires, defer_measurements, decompose, validate_measurements, - validate_observables) + >>> qml.workflow.get_transform_program(circuit, level="device") + TransformProgram(cancel_inverses, merge_rotations, _expand_transform_param_shift, + validate_device_wires, defer_measurements, decompose, validate_measurements, + validate_observables) - ``"top"`` and ``0`` both return empty transform programs. + ``"top"`` and ``0`` both return empty transform programs. - >>> qml.workflow.get_transform_program(circuit, level="top") - TransformProgram() - >>> qml.workflow.get_transform_program(circuit, level=0) - TransformProgram() + >>> qml.workflow.get_transform_program(circuit, level="top") + TransformProgram() + >>> qml.workflow.get_transform_program(circuit, level=0) + TransformProgram() - The ``level`` can also be any integer, corresponding to a number of transforms in the program. + The ``level`` can also be any integer, corresponding to a number of transforms in the program. - >>> qml.workflow.get_transform_program(circuit, level=2) - TransformProgram(cancel_inverses, merge_rotations) + >>> qml.workflow.get_transform_program(circuit, level=2) + TransformProgram(cancel_inverses, merge_rotations) - ``level`` can also accept a ``slice`` object to select out any arbitrary subset of the - transform program. This allows you to select different starting transforms or strides. - For example, you can skip the first transform or reverse the order: + ``level`` can also accept a ``slice`` object to select out any arbitrary subset of the + transform program. This allows you to select different starting transforms or strides. + For example, you can skip the first transform or reverse the order: - >>> qml.workflow.get_transform_program(circuit, level=slice(1,3)) - TransformProgram(merge_rotations, _expand_transform_param_shift) - >>> qml.workflow.get_transform_program(circuit, level=slice(None, None, -1)) - TransformProgram(metric_tensor, validate_observables, validate_measurements, - decompose, defer_measurements, validate_device_wires, _expand_transform_param_shift, - _expand_metric_tensor, merge_rotations, cancel_inverses) + >>> qml.workflow.get_transform_program(circuit, level=slice(1,3)) + TransformProgram(merge_rotations, _expand_transform_param_shift) + >>> qml.workflow.get_transform_program(circuit, level=slice(None, None, -1)) + TransformProgram(metric_tensor, validate_observables, validate_measurements, + decompose, defer_measurements, validate_device_wires, _expand_transform_param_shift, + _expand_metric_tensor, merge_rotations, cancel_inverses) """ full_transform_program = _get_full_transform_program(qnode) @@ -201,83 +203,87 @@ def construct_batch(qnode: QNode, level: Union[None, str, int, slice] = "user") .. seealso:: :func:`pennylane.workflow.get_transform_program` to inspect the contents of the transform program for a specified level. - Suppose we have a QNode with several user transforms. - - .. code-block:: python - - @qml.transforms.undo_swaps - @qml.transforms.merge_rotations - @qml.transforms.cancel_inverses - @qml.qnode(qml.device('default.qubit'), diff_method="parameter-shift", shifts=np.pi / 4) - def circuit(x): - qml.RandomLayers(qml.numpy.array([[1.0, 2.0]]), wires=(0,1)) - qml.RX(x, wires=0) - qml.RX(-x, wires=0) - qml.SWAP((0,1)) - qml.PauliX(0) - qml.PauliX(0) - return qml.expval(qml.PauliX(0) + qml.PauliY(0)) - - We can inspect what the device will execute with: - - >>> batch, fn = construct_batch(circuit, level="device")(1.23) - >>> batch[0].circuit - [RY(tensor(1., requires_grad=True), wires=[1]), - RX(tensor(2., requires_grad=True), wires=[0]), - expval( (1) [X0] - + (1) [Y0])] - - These tapes can be natively executed by the device, though with non-backprop devices the parameters - will need to be converted to numpy with :func:`~.convert_to_numpy_parameters`. - - >>> fn(dev.execute(batch)) - (tensor(-0.90929743, requires_grad=True),) - - Or what the parameter shift gradient transform will be applied to: - - >>> batch, fn = construct_batch(circuit, level="gradient")(1.23) - >>> batch[0].circuit - [RY(tensor(1., requires_grad=True), wires=[1]), - RX(tensor(2., requires_grad=True), wires=[0]), - expval( (1) [X0] - + (1) [Y0])] - - We can inspect what was directly captured from the qfunc with ``level=0``. - - >>> batch, fn = construct_batch(circuit, level=0)(1.23) - >>> batch[0].circuit - [RandomLayers(tensor([[1., 2.]], requires_grad=True), wires=[0, 1]), - RX(1.23, wires=[0]), - RX(-1.23, wires=[0]), - SWAP(wires=[0, 1]), - PauliX(wires=[0]), - PauliX(wires=[0]), - expval( (1) [X0] - + (1) [Y0])] - - And iterate though stages in the transform program with different integers. - If we request ``level=1``, the ``cancel_inverses`` transform has been applied. - - >>> batch, fn = construct_batch(circuit, level=1)(1.23) - >>> batch[0].circuit - [RandomLayers(tensor([[1., 2.]], requires_grad=True), wires=[0, 1]), - RX(1.23, wires=[0]), - RX(-1.23, wires=[0]), - SWAP(wires=[0, 1]), - expval( (1) [X0] - + (1) [Y0])] - - We can also slice into a subset of the transform program. ``slice(1, None)`` would skip the first user - transform ``cancel_inverses``: - - >>> batch, fn = construct_batch(circuit, level=slice(1,None))(1.23) - >>> batch[0].circuit - [RY(tensor(1., requires_grad=True), wires=[1]), - RX(tensor(2., requires_grad=True), wires=[0]), - PauliX(wires=[0]), - PauliX(wires=[0]), - expval( (1) [X0] - + (1) [Y0])] + + .. details:: + :title: Usage Details + + Suppose we have a QNode with several user transforms. + + .. code-block:: python + + @qml.transforms.undo_swaps + @qml.transforms.merge_rotations + @qml.transforms.cancel_inverses + @qml.qnode(qml.device('default.qubit'), diff_method="parameter-shift", shifts=np.pi / 4) + def circuit(x): + qml.RandomLayers(qml.numpy.array([[1.0, 2.0]]), wires=(0,1)) + qml.RX(x, wires=0) + qml.RX(-x, wires=0) + qml.SWAP((0,1)) + qml.PauliX(0) + qml.PauliX(0) + return qml.expval(qml.PauliX(0) + qml.PauliY(0)) + + We can inspect what the device will execute with: + + >>> batch, fn = construct_batch(circuit, level="device")(1.23) + >>> batch[0].circuit + [RY(tensor(1., requires_grad=True), wires=[1]), + RX(tensor(2., requires_grad=True), wires=[0]), + expval( (1) [X0] + + (1) [Y0])] + + These tapes can be natively executed by the device, though with non-backprop devices the parameters + will need to be converted to numpy with :func:`~.convert_to_numpy_parameters`. + + >>> fn(dev.execute(batch)) + (tensor(-0.90929743, requires_grad=True),) + + Or what the parameter shift gradient transform will be applied to: + + >>> batch, fn = construct_batch(circuit, level="gradient")(1.23) + >>> batch[0].circuit + [RY(tensor(1., requires_grad=True), wires=[1]), + RX(tensor(2., requires_grad=True), wires=[0]), + expval( (1) [X0] + + (1) [Y0])] + + We can inspect what was directly captured from the qfunc with ``level=0``. + + >>> batch, fn = construct_batch(circuit, level=0)(1.23) + >>> batch[0].circuit + [RandomLayers(tensor([[1., 2.]], requires_grad=True), wires=[0, 1]), + RX(1.23, wires=[0]), + RX(-1.23, wires=[0]), + SWAP(wires=[0, 1]), + PauliX(wires=[0]), + PauliX(wires=[0]), + expval( (1) [X0] + + (1) [Y0])] + + And iterate though stages in the transform program with different integers. + If we request ``level=1``, the ``cancel_inverses`` transform has been applied. + + >>> batch, fn = construct_batch(circuit, level=1)(1.23) + >>> batch[0].circuit + [RandomLayers(tensor([[1., 2.]], requires_grad=True), wires=[0, 1]), + RX(1.23, wires=[0]), + RX(-1.23, wires=[0]), + SWAP(wires=[0, 1]), + expval( (1) [X0] + + (1) [Y0])] + + We can also slice into a subset of the transform program. ``slice(1, None)`` would skip the first user + transform ``cancel_inverses``: + + >>> batch, fn = construct_batch(circuit, level=slice(1,None))(1.23) + >>> batch[0].circuit + [RY(tensor(1., requires_grad=True), wires=[1]), + RX(tensor(2., requires_grad=True), wires=[0]), + PauliX(wires=[0]), + PauliX(wires=[0]), + expval( (1) [X0] + + (1) [Y0])] """ program = get_transform_program(qnode, level=level) From c667da297abc6827dbf9780dff3776bb74a2d2f6 Mon Sep 17 00:00:00 2001 From: albi3ro Date: Wed, 31 Jan 2024 11:22:00 -0500 Subject: [PATCH 19/19] set seed in flaky test --- tests/test_hermitian_edge_cases.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_hermitian_edge_cases.py b/tests/test_hermitian_edge_cases.py index b3f2365ebf2..d628cf268ff 100644 --- a/tests/test_hermitian_edge_cases.py +++ b/tests/test_hermitian_edge_cases.py @@ -91,7 +91,7 @@ def circuit(): @pytest.mark.parametrize("w1, w2", list(itertools.permutations(range(4), 2))) def test_hermitian_two_wires_permuted(self, w1, w2, shots, theta): """Test that an hermitian expectation with various wires permuted works""" - dev = qml.device("default.qubit", wires=4, shots=shots) + dev = qml.device("default.qubit", wires=4, shots=shots, seed=123545) theta = 0.543 A = np.array(