Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 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
36 changes: 36 additions & 0 deletions doc/development/deprecations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,42 @@ deprecations are listed below.
Pending deprecations
--------------------

* Providing ``num_steps`` to ``qml.evolve`` and ``Evolution`` is deprecated and will be removed in a future version.
Instead, you can use :class:`~.TrotterProduct` providing the ``n`` parameter to perform the
Suzuki-Trotter product approximation of a Hamiltonian with the specified number of Trotter steps.

As a concrete example, consider the following case:

```python
coeffs = [0.5, -0.6]
ops = [qml.X(0), qml.X(0) @ qml.Y(1)]
H_flat = qml.dot(coeffs, ops)
```

Instead of computing the Suzuki-Trotter product approximation as:

```pycon
>>> qml.evolve(H_flat, num_steps=2).decomposition()
[RX(0.5, wires=[0]),
PauliRot(-0.6, XY, wires=[0, 1]),
RX(0.5, wires=[0]),
PauliRot(-0.6, XY, wires=[0, 1])]
```

The same result can be obtained using :class:`~.TrotterProduct` as follows:

```pycon
>>> decomp_ops = qml.adjoint(qml.TrotterProduct(H_flat, time=1.0, n=2)).decomposition()
>>> [simp_op for op in decomp_ops for simp_op in map(qml.simplify, op.decomposition())]
[RX(0.5, wires=[0]),
PauliRot(-0.6, XY, wires=[0, 1]),
RX(0.5, wires=[0]),
PauliRot(-0.6, XY, wires=[0, 1])]
```

- Deprecated in v0.43
- Will be removed in a future version

* ``shots=`` in ``QNode`` calls is deprecated and will be removed in v0.44.
Instead, please use the ``qml.workflow.set_shots`` transform to set the number of shots for a ``QNode``.

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

<h3>Deprecations 👋</h3>

* Providing `num_steps` to `qml.evolve` and `Evolution` is deprecated and will be removed in a future version.
Instead, you can use :class:`~.TrotterProduct` providing the `n` parameter to perform the
Suzuki-Trotter product approximation of a Hamiltonian with the specified number of Trotter steps.

As a concrete example, consider the following case:

```python
coeffs = [0.5, -0.6]
ops = [qml.X(0), qml.X(0) @ qml.Y(1)]
H_flat = qml.dot(coeffs, ops)
```

Instead of computing the Suzuki-Trotter product approximation as:

```pycon
>>> qml.evolve(H_flat, num_steps=2).decomposition()
[RX(0.5, wires=[0]),
PauliRot(-0.6, XY, wires=[0, 1]),
RX(0.5, wires=[0]),
PauliRot(-0.6, XY, wires=[0, 1])]
```

The same result can be obtained using :class:`~.TrotterProduct` as follows:

```pycon
>>> decomp_ops = qml.adjoint(qml.TrotterProduct(H_flat, time=1.0, n=2)).decomposition()
>>> [simp_op for op in decomp_ops for simp_op in map(qml.simplify, op.decomposition())]
[RX(0.5, wires=[0]),
PauliRot(-0.6, XY, wires=[0, 1]),
RX(0.5, wires=[0]),
PauliRot(-0.6, XY, wires=[0, 1])]
```
[(#7954)](https://github.com/PennyLaneAI/pennylane/pull/7954)

* `shots=` in `QNode` calls is deprecated and will be removed in v0.44.
Instead, please use the `qml.workflow.set_shots` transform to set the number of shots for a QNode.
[(#7906)](https://github.com/PennyLaneAI/pennylane/pull/7906)
Expand Down
38 changes: 38 additions & 0 deletions pennylane/ops/functions/evolve.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
"""
from functools import singledispatch
from typing import overload
from warnings import warn

from pennylane.exceptions import PennyLaneDeprecationWarning
from pennylane.operation import Operator
from pennylane.ops import Evolution
from pennylane.pulse import ParametrizedEvolution, ParametrizedHamiltonian
Expand Down Expand Up @@ -54,6 +56,35 @@ def evolve(*args, **kwargs): # pylint: disable=unused-argument
Returns:
.Evolution: evolution operator

.. warning::

Providing ``num_steps`` to ``qml.evolve`` and ``Evolution`` is deprecated and will be removed in a future version.
Instead, you can use :class:`~.TrotterProduct` providing the ``n`` parameter to perform the
Suzuki-Trotter product approximation of a Hamiltonian with the specified number of Trotter steps.

As a concrete example, consider the following case:

>>> coeffs = [0.5, -0.6]
>>> ops = [qml.X(0), qml.X(0) @ qml.Y(1)]
>>> H_flat = qml.dot(coeffs, ops)

Instead of computing the Suzuki-Trotter product approximation as:

>>> qml.evolve(H_flat, num_steps=2).decomposition()
[RX(0.5, wires=[0]),
PauliRot(-0.6, XY, wires=[0, 1]),
RX(0.5, wires=[0]),
PauliRot(-0.6, XY, wires=[0, 1])]

The same result can be obtained using :class:`~.TrotterProduct` as follows:

>>> decomp_ops = qml.adjoint(qml.TrotterProduct(H_flat, time=1.0, n=2)).decomposition()
>>> [simp_op for op in decomp_ops for simp_op in map(qml.simplify, op.decomposition())]
[RX(0.5, wires=[0]),
PauliRot(-0.6, XY, wires=[0, 1]),
RX(0.5, wires=[0]),
PauliRot(-0.6, XY, wires=[0, 1])]

**Examples**

We can use ``qml.evolve`` to compute the evolution of any PennyLane operator:
Expand Down Expand Up @@ -178,4 +209,11 @@ def parametrized_evolution(op: ParametrizedHamiltonian, **kwargs):
# pylint: disable=missing-docstring
@evolve.register
def evolution(op: Operator, coeff: float = 1, num_steps: int = None):
if num_steps is not None:
warn(
"Providing ``num_steps`` to ``qml.evolve`` and ``Evolution`` is deprecated and will be removed in a future version. "
"Instead, you can use ``qml.TrotterProduct`` providing the ``n`` parameter to perform the "
"Suzuki-Trotter product approximation of a Hamiltonian with the specified number of Trotter steps.",
PennyLaneDeprecationWarning,
)
return Evolution(op, coeff, num_steps)
38 changes: 37 additions & 1 deletion pennylane/ops/op_math/evolution.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

import pennylane as qml
from pennylane import math
from pennylane.exceptions import GeneratorUndefinedError
from pennylane.exceptions import GeneratorUndefinedError, PennyLaneDeprecationWarning

from .exp import Exp

Expand All @@ -40,6 +40,35 @@ class Evolution(Exp):
:class:`Evolution`: A :class:`~.operation.Operator` representing an operator exponential of the form :math:`e^{-ix\hat{G}}`,
where x is real.

.. warning::

Providing ``num_steps`` to ``qml.evolve`` and ``Evolution`` is deprecated and will be removed in a future version.
Instead, you can use :class:`~.TrotterProduct` providing the ``n`` parameter to perform the
Suzuki-Trotter product approximation of a Hamiltonian with the specified number of Trotter steps.

As a concrete example, consider the following case:

>>> coeffs = [0.5, -0.6]
>>> ops = [qml.X(0), qml.X(0) @ qml.Y(1)]
>>> H_flat = qml.dot(coeffs, ops)

Instead of computing the Suzuki-Trotter product approximation as:

>>> qml.ops.op_math.Evolution(H_flat, num_steps=2).decomposition()
[RX(0.5, wires=[0]),
PauliRot(-0.6, XY, wires=[0, 1]),
RX(0.5, wires=[0]),
PauliRot(-0.6, XY, wires=[0, 1])]

The same result can be obtained using :class:`~.TrotterProduct` as follows:

>>> decomp_ops = qml.adjoint(qml.TrotterProduct(H_flat, time=1.0, n=2)).decomposition()
>>> [simp_op for op in decomp_ops for simp_op in map(qml.simplify, op.decomposition())]
[RX(0.5, wires=[0]),
PauliRot(-0.6, XY, wires=[0, 1]),
RX(0.5, wires=[0]),
PauliRot(-0.6, XY, wires=[0, 1])]

**Usage Details**

In contrast to the general :class:`~.Exp` class, the ``Evolution`` operator :math:`e^{-ix\hat{G}}` is constrained to have a single trainable
Expand Down Expand Up @@ -78,6 +107,13 @@ class Evolution(Exp):
num_params = 1

def __init__(self, generator, param=1, num_steps=None, id=None):
if num_steps is not None:
warn(
"Providing ``num_steps`` to ``qml.evolve`` and ``Evolution`` is deprecated and will be removed in a future version. "
"Instead, you can use ``qml.TrotterProduct`` providing the ``n`` parameter to perform the "
"Suzuki-Trotter product approximation of a Hamiltonian with the specified number of Trotter steps.",
PennyLaneDeprecationWarning,
)
super().__init__(generator, coeff=-1j * param, num_steps=num_steps, id=id)
self._data = (param,)

Expand Down
20 changes: 10 additions & 10 deletions tests/ops/functions/test_bind_new_parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from gate_data import GELL_MANN, I, X, Y, Z

import pennylane as qml
from pennylane.exceptions import PennyLaneDeprecationWarning
from pennylane.ops.functions import bind_new_parameters


Expand Down Expand Up @@ -91,21 +92,20 @@ def test_composite_ops(op, new_params, expected_op):
assert all(no is not o for no, o in zip(new_op.operands, op.operands))


def test_num_steps_is_deprecated():
"""Test that providing `num_steps` to `qml.evolve` raises a deprecation warning."""
with pytest.warns(
PennyLaneDeprecationWarning,
match="Providing ``num_steps`` to ``qml.evolve`` and ``Evolution`` is deprecated",
):
qml.evolve(qml.PauliX(0), 0.5, num_steps=15)


@pytest.mark.parametrize(
"op, new_params, expected_op",
[
(qml.evolve(qml.PauliX(0), 0.5), [-0.5], qml.evolve(qml.PauliX(0), -0.5)),
(
qml.evolve(qml.PauliX(0), 0.5, num_steps=15),
[-0.5],
qml.evolve(qml.PauliX(0), -0.5, num_steps=15),
),
(qml.exp(qml.PauliX(0), 0.5), [-0.5], qml.exp(qml.PauliX(0), -0.5)),
(
qml.exp(qml.PauliX(0), 0.5, num_steps=15),
[-0.5],
qml.exp(qml.PauliX(0), -0.5, num_steps=15),
),
(qml.pow(qml.RX(0.123, 0), 2), [0.456], qml.pow(qml.RX(0.456, 0), 2)),
(qml.s_prod(0.5, qml.RX(0.123, 0)), [-0.5, 0.456], qml.s_prod(-0.5, qml.RX(0.456, 0))),
(
Expand Down
37 changes: 32 additions & 5 deletions tests/ops/op_math/test_exp.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
DecompositionUndefinedError,
GeneratorUndefinedError,
ParameterFrequenciesUndefinedError,
PennyLaneDeprecationWarning,
)
from pennylane.ops.op_math import Evolution, Exp
from pennylane.ops.op_math.exp import trotter_decomp
Expand Down Expand Up @@ -502,7 +503,12 @@ def test_trotter_is_used_if_num_steps_is_defined(self):
phi = 1.23
num_steps = 3
op = qml.IsingXY(phi, wires=[0, 1])
exp = qml.evolve(op.generator(), coeff=-phi, num_steps=num_steps)
with pytest.warns(
PennyLaneDeprecationWarning,
match="Providing ``num_steps`` to ``qml.evolve`` and ``Evolution`` is deprecated",
):
exp = qml.evolve(op.generator(), coeff=-phi, num_steps=num_steps)

dec = exp.decomposition()
assert qml.math.allclose(
qml.matrix(qml.tape.QuantumScript(dec), wire_order=[0, 1]),
Expand Down Expand Up @@ -680,11 +686,10 @@ def test_repr_paulix(self):
assert repr(op) == "Exp(3 PauliX)"

# pylint: disable=protected-access
@pytest.mark.parametrize("exp_type", (Exp, Evolution))
def test_flatten_unflatten(self, exp_type):
"""Tests the _unflatten and _flatten methods."""
def test_flatten_unflatten_Exp(self):
"""Tests the _unflatten and _flatten methods for the Exp operator."""
base = qml.RX(1.2, wires=0)
op = exp_type(base, 2.5, num_steps=5)
op = Exp(base, 2.5, num_steps=5)

data, metadata = op._flatten()
assert data[0] is base
Expand All @@ -697,6 +702,28 @@ def test_flatten_unflatten(self, exp_type):
new_op = type(op)._unflatten(*op._flatten())
qml.assert_equal(new_op, op)

# pylint: disable=protected-access
def test_flatten_unflatten_Evolution(self):
"""Tests the _unflatten and _flatten methods for the Evolution operator."""
base = qml.RX(1.2, wires=0)
op = Evolution(base, 2.5)

data, _ = op._flatten()
assert data[0] is base
assert data[1] == 2.5

new_op = type(op)._unflatten(*op._flatten())
qml.assert_equal(new_op, op)

def test_num_steps_is_deprecated(self):
"""Test that providing `num_steps` raises a deprecation warning."""
with pytest.warns(
PennyLaneDeprecationWarning,
match="Providing ``num_steps`` to ``qml.evolve`` and ``Evolution`` is deprecated",
):
base = qml.RX(1.2, wires=0)
Evolution(base, 2.5, num_steps=5)

def test_repr_tensor(self):
"""Test the __repr__ method when the base is a tensor."""
t = qml.PauliX(0) @ qml.PauliX(1)
Expand Down