Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Deprecate inner_transform_program and config arguments to qml.execute #6822

Merged
merged 20 commits into from
Jan 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions doc/development/deprecations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ deprecations are listed below.
Pending deprecations
--------------------

* The ``inner_transform_program`` and ``config`` keyword arguments in ``qml.execute`` have been deprecated.
If more detailed control over the execution is required, use ``qml.workflow.run`` with these arguments instead.

- Deprecated in v0.41
- Will be removed in v0.42

* ``op.ops`` and ``op.coeffs`` for ``Sum`` and ``Prod`` will be removed in the future. Use
:meth:`~.Operator.terms` instead.

Expand Down
7 changes: 7 additions & 0 deletions doc/releases/changelog-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@

<h3>Breaking changes 💔</h3>

* `qml.execute` now has a collection of keyword-only arguments.
[(#6598)](https://github.com/PennyLaneAI/pennylane/pull/6598)

* The ``decomp_depth`` argument in :func:`~pennylane.transforms.set_decomposition` has been removed.
[(#6824)](https://github.com/PennyLaneAI/pennylane/pull/6824)

Expand All @@ -71,6 +74,10 @@

<h3>Deprecations 👋</h3>

* The ``inner_transform_program`` and ``config`` keyword arguments in ``qml.execute`` have been deprecated.
If more detailed control over the execution is required, use ``qml.workflow.run`` with these arguments instead.
[(#6822)](https://github.com/PennyLaneAI/pennylane/pull/6822)

<h3>Documentation 📝</h3>

* Updated documentation for vibrational Hamiltonians
Expand Down
91 changes: 52 additions & 39 deletions pennylane/workflow/execution.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,19 @@

import inspect
import logging
from collections.abc import Callable
from dataclasses import replace
from typing import Optional, Union
from typing import Callable, Literal, Optional, Union
from warnings import warn

from cachetools import Cache

import pennylane as qml
from pennylane.math import Interface
from pennylane.math.interface_utils import InterfaceLike
from pennylane.tape import QuantumScriptBatch
from pennylane.transforms.core import TransformDispatcher, TransformProgram
from pennylane.typing import ResultBatch
from pennylane.workflow.resolution import SupportedDiffMethods

from ._setup_transform_program import _setup_transform_program
from .resolution import _resolve_execution_config, _resolve_interface
Expand All @@ -41,19 +44,19 @@
def execute(
tapes: QuantumScriptBatch,
device: Union["qml.devices.LegacyDevice", "qml.devices.Device"],
diff_method: Optional[Union[Callable, str, qml.transforms.core.TransformDispatcher]] = None,
interface: Optional[Union[str, Interface]] = Interface.AUTO,
diff_method: Optional[Union[Callable, SupportedDiffMethods, TransformDispatcher]] = None,
interface: Optional[InterfaceLike] = Interface.AUTO,
*,
transform_program=None,
inner_transform=None,
astralcai marked this conversation as resolved.
Show resolved Hide resolved
config=None,
grad_on_execution="best",
gradient_kwargs=None,
grad_on_execution: Literal[bool, "best"] = "best",
cache: Union[None, bool, dict, Cache] = True,
cachesize=10000,
max_diff=1,
device_vjp=False,
mcm_config=None,
cachesize: int = 10000,
max_diff: int = 1,
device_vjp: Union[bool, None] = False,
gradient_kwargs: dict = None,
transform_program: TransformProgram = None,
mcm_config: "qml.devices.MCMConfig" = None,
config="unset",
inner_transform="unset",
) -> ResultBatch:
"""A function for executing a batch of tapes on a device with compatibility for auto-differentiation.

Expand All @@ -69,17 +72,11 @@ def execute(
This affects the types of parameters that can exist on the input tapes.
Available options include ``autograd``, ``torch``, ``tf``, ``jax``, and ``auto``.
transform_program(.TransformProgram): A transform program to be applied to the initial tape.
inner_transform (.TransformProgram): A transform program to be applied to the tapes in
inner execution, inside the ml interface.
config (qml.devices.ExecutionConfig): A data structure describing the parameters
needed to fully describe the execution.
grad_on_execution (bool, str): Whether the gradients should be computed
on the execution or not. It only applies
if the device is queried for the gradient; gradient transform
functions available in ``qml.gradients`` are only supported on the backward
pass. The 'best' option chooses automatically between the two options and is default.
gradient_kwargs (dict): dictionary of keyword arguments to pass when
determining the gradients of tapes.
cache (None, bool, dict, Cache): Whether to cache evaluations. This can result in
a significant reduction in quantum evaluations during gradient computations.
cachesize (int): the size of the cache.
Expand All @@ -91,6 +88,12 @@ def execute(
product if it is available.
mcm_config (dict): Dictionary containing configuration options for handling
mid-circuit measurements.
gradient_kwargs (dict): dictionary of keyword arguments to pass when
determining the gradients of tapes.
config="unset": **DEPRECATED**. This keyword argument has been deprecated and
will be removed in v0.42.
inner_transform="unset": **DEPRECATED**. This keyword argument has been deprecated
and will be removed in v0.42.

Returns:
list[tensor_like[float]]: A nested list of tape results. Each element in
Expand Down Expand Up @@ -154,6 +157,22 @@ def cost_fn(params, x):
if not isinstance(device, qml.devices.Device):
device = qml.devices.LegacyDeviceFacade(device)

if config != "unset":
warn(
"The config argument has been deprecated and will be removed in v0.42. "
"The provided config argument will be ignored. "
"If more detailed control over the execution is required, use ``qml.workflow.run`` with these arguments instead.",
qml.PennyLaneDeprecationWarning,
)

if inner_transform != "unset":
warn(
"The inner_transform argument has been deprecated and will be removed in v0.42. "
"The provided inner_transform argument will be ignored. "
"If more detailed control over the execution is required, use ``qml.workflow.run`` with these arguments instead.",
qml.PennyLaneDeprecationWarning,
)

if logger.isEnabledFor(logging.DEBUG):
logger.debug(
(
Expand Down Expand Up @@ -185,33 +204,27 @@ def cost_fn(params, x):
interface = _resolve_interface(interface, tapes)
# Only need to calculate derivatives with jax when we know it will be executed later.

gradient_kwargs = gradient_kwargs or {}
mcm_config = mcm_config or {}
if not config:
config = qml.devices.ExecutionConfig(
interface=interface,
gradient_method=diff_method,
grad_on_execution=None if grad_on_execution == "best" else grad_on_execution,
use_device_jacobian_product=device_vjp,
mcm_config=mcm_config,
gradient_keyword_arguments=gradient_kwargs,
derivative_order=max_diff,
)
config = _resolve_execution_config(
config, device, tapes, transform_program=transform_program
)
config = qml.devices.ExecutionConfig(
interface=interface,
gradient_method=diff_method,
grad_on_execution=None if grad_on_execution == "best" else grad_on_execution,
use_device_jacobian_product=device_vjp,
mcm_config=mcm_config or {},
gradient_keyword_arguments=gradient_kwargs or {},
derivative_order=max_diff,
)
config = _resolve_execution_config(config, device, tapes, transform_program=transform_program)

config = replace(
config,
interface=interface,
derivative_order=max_diff,
)

if transform_program is None or inner_transform is None:
transform_program = transform_program or qml.transforms.core.TransformProgram()
transform_program, inner_transform = _setup_transform_program(
transform_program, device, config, cache, cachesize
)
transform_program = transform_program or qml.transforms.core.TransformProgram()
transform_program, inner_transform = _setup_transform_program(
transform_program, device, config, cache, cachesize
)

#### Executing the configured setup #####
tapes, post_processing = transform_program(tapes)
Expand Down
22 changes: 22 additions & 0 deletions tests/workflow/interfaces/execute/test_execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,28 @@ def test_execute_legacy_device():
assert qml.math.allclose(res[0], np.cos(0.1))


def test_config_deprecation():
"""Test that the config argument has been deprecated."""

tape = qml.tape.QuantumScript([qml.RX(qml.numpy.array(1.0), 0)], [qml.expval(qml.Z(0))])
dev = qml.device("default.qubit")
with pytest.warns(
qml.PennyLaneDeprecationWarning, match="The config argument has been deprecated"
):
qml.execute((tape,), dev, config=qml.devices.DefaultExecutionConfig)


def test_inner_transform_program_deprecation():
"""Test that the inner_transform argument has been deprecated."""

tape = qml.tape.QuantumScript([qml.RX(qml.numpy.array(1.0), 0)], [qml.expval(qml.Z(0))])
dev = qml.device("default.qubit")
with pytest.warns(
qml.PennyLaneDeprecationWarning, match="The inner_transform argument has been deprecated"
):
qml.execute((tape,), dev, inner_transform=qml.transforms.core.TransformProgram())


def test_execution_with_empty_batch():
"""Test that qml.execute can be used with an empty batch."""

Expand Down
Loading