Skip to content

Commit

Permalink
Miscellaneous deprecations (#6277)
Browse files Browse the repository at this point in the history
* Deprecate `qml.broadcast`.
* Deprecate `qml.shadows.shadow_expval`.
* Deprecate the `'ancilla'` argument of `qml.iterative_qpe`in favour of
`aux_wire`.

[sc-69798] [sc-72497] [sc-71185]

---------

Co-authored-by: David Wierichs <david.wierichs@xanadu.ai>
Co-authored-by: lillian542 <38584660+lillian542@users.noreply.github.com>
  • Loading branch information
3 people committed Sep 17, 2024
1 parent 2c0fdf0 commit a40e3e7
Show file tree
Hide file tree
Showing 16 changed files with 201 additions and 43 deletions.
19 changes: 18 additions & 1 deletion doc/development/deprecations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,23 @@ deprecations are listed below.
Pending deprecations
--------------------

* The ``'ancilla'`` argument for :func:`~pennylane.iterative_qpe` has been deprecated. Instead, use the ``'aux_wire'``
argument.

- Deprecated in v0.39
- Will be removed in v0.40

* The ``qml.shadows.shadow_expval`` transform has been deprecated. Instead, please use the
``qml.shadow_expval`` measurement process.

- Deprecated in v0.39
- Will be removed in v0.40

* ``qml.broadcast`` has been deprecated. Users should use ``for`` loops instead.

- Deprecated in v0.39
- Will be removed in v0.40

* The ``qml.qinfo`` module has been deprecated. Please see the respective functions in the ``qml.math`` and ``qml.measurements``
modules instead.

Expand All @@ -22,7 +39,7 @@ Pending deprecations
- Deprecated top level access in v0.39
- Top level access will be removed in v0.40

* `QNode.gradient_fn` is deprecated. Please use `QNode.diff_method` instead. `QNode.get_gradient_fn` can also be used to
* ``QNode.gradient_fn`` is deprecated. Please use ``QNode.diff_method`` instead. ``QNode.get_gradient_fn`` can also be used to
process the diff method.

- Deprecated in v0.39
Expand Down
25 changes: 17 additions & 8 deletions doc/releases/changelog-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,14 +97,23 @@

<h3>Deprecations 👋</h3>

* The `'ancilla'` argument for `qml.iterative_qpe` has been deprecated. Instead, use the `'aux_wire'` argument.
[(#6277)](https://github.com/PennyLaneAI/pennylane/pull/6277)

* `qml.shadows.shadow_expval` has been deprecated. Instead, use the `qml.shadow_expval` measurement
process.
[(#6277)](https://github.com/PennyLaneAI/pennylane/pull/6277)

* `qml.broadcast` has been deprecated. Please use `for` loops instead.
[(#6277)](https://github.com/PennyLaneAI/pennylane/pull/6277)

* The `qml.QubitStateVector` template is deprecated. Instead, use `qml.StatePrep`.
[(#6172)](https://github.com/PennyLaneAI/pennylane/pull/6172)

* The `qml.qinfo` module has been deprecated. Please see the respective functions in the `qml.math` and
`qml.measurements` modules instead.
[(#5911)](https://github.com/PennyLaneAI/pennylane/pull/5911)

* The ``QubitStateVector`` template is deprecated.
Instead, use ``StatePrep``.
[(#6172)](https://github.com/PennyLaneAI/pennylane/pull/6172)

* `Device`, `QubitDevice`, and `QutritDevice` will no longer be accessible via top-level import in v0.40.
They will still be accessible as `qml.devices.LegacyDevice`, `qml.devices.QubitDevice`, and `qml.devices.QutritDevice`
respectively.
Expand All @@ -120,19 +129,19 @@
* Fix a bug where zero-valued JVPs were calculated wrongly in the presence of shot vectors.
[(#6219)](https://github.com/PennyLaneAI/pennylane/pull/6219)

* Fix `qml.PrepSelPrep` template to work with `torch`:
* Fix `qml.PrepSelPrep` template to work with `torch`.
[(#6191)](https://github.com/PennyLaneAI/pennylane/pull/6191)

* Now `qml.equal` compares correctly `qml.PrepSelPrep` operators.
[(#6182)](https://github.com/PennyLaneAI/pennylane/pull/6182)

* The ``qml.QSVT`` template now orders the ``projector`` wires first and the ``UA`` wires second, which is the expected order of the decomposition.
* The `qml.QSVT` template now orders the `projector` wires first and the `UA` wires second, which is the expected order of the decomposition.
[(#6212)](https://github.com/PennyLaneAI/pennylane/pull/6212)

* The ``qml.Qubitization`` template now orders the ``control`` wires first and the ``hamiltonian`` wires second, which is the expected according to other templates.
* The `qml.Qubitization` template now orders the `control` wires first and the `hamiltonian` wires second, which is the expected according to other templates.
[(#6229)](https://github.com/PennyLaneAI/pennylane/pull/6229)

* The ``qml.FABLE`` template now returns the correct value when JIT is enabled.
* The `qml.FABLE` template now returns the correct value when JIT is enabled.
[(#6263)](https://github.com/PennyLaneAI/pennylane/pull/6263)

* Fixes a bug where a circuit using the `autograd` interface sometimes returns nested values that are not of the `autograd` interface.
Expand Down
2 changes: 1 addition & 1 deletion pennylane/devices/_qubit_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -1153,7 +1153,7 @@ def classical_shadow(self, obs, circuit):
def shadow_expval(self, obs, circuit):
r"""Compute expectation values using classical shadows in a differentiable manner.
Please refer to :func:`~.pennylane.shadow_expval` for detailed documentation.
Please refer to :func:`~pennylane.shadow_expval` for detailed documentation.
Args:
obs (~.pennylane.measurements.ClassicalShadowMP): The classical shadow expectation
Expand Down
2 changes: 1 addition & 1 deletion pennylane/devices/_qutrit_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ def classical_shadow(self, obs, circuit):
def shadow_expval(self, obs, circuit):
r"""Compute expectation values using classical shadows in a differentiable manner.
Please refer to :func:`~.pennylane.shadow_expval` for detailed documentation.
Please refer to :func:`~pennylane.shadow_expval` for detailed documentation.
.. seealso:: :func:`~pennylane.shadow_expval`
Expand Down
2 changes: 1 addition & 1 deletion pennylane/measurements/classical_shadow.py
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,7 @@ def __copy__(self):
class ShadowExpvalMP(MeasurementTransform):
"""Measures the expectation value of an operator using the classical shadow measurement process.
Please refer to :func:`shadow_expval` for detailed documentation.
Please refer to :func:`~pennylane.shadow_expval` for detailed documentation.
Args:
H (Operator, Sequence[Operator]): Operator or list of Operators to compute the expectation value over.
Expand Down
41 changes: 33 additions & 8 deletions pennylane/ops/functions/iterative_qpe.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,26 @@
This module contains the qml.iterative_qpe function.
"""

from warnings import warn

import numpy as np

import pennylane as qml


def iterative_qpe(base, ancilla, iters):
def iterative_qpe(base, aux_wire="unset", iters="unset", ancilla="unset"):
r"""Performs the `iterative quantum phase estimation <https://arxiv.org/pdf/quant-ph/0610214.pdf>`_ circuit.
Given a unitary :math:`U`, this function applies the circuit for iterative quantum phase
estimation and returns a list of mid-circuit measurements with qubit reset.
Args:
base (Operator): the phase estimation unitary, specified as an :class:`~.Operator`
ancilla (Union[Wires, int, str]): the wire to be used for the estimation
aux_wire (Union[Wires, int, str]): the wire to be used for the estimation
iters (int): the number of measurements to be performed
ancilla (Union[Wires, int, str]): the wire to be used for the estimation. This argument
is deprecated, and the ``aux_wire`` argument should be used instead. If both arguments
are provided, ``aux_wire`` will be used and ``ancilla`` will be ignored.
Returns:
list[MidMeasureMP]: the list of measurements performed
Expand All @@ -49,7 +54,7 @@ def circuit():
qml.X(0)
# Iterative QPE
measurements = qml.iterative_qpe(qml.RZ(2.0, wires=[0]), ancilla=1, iters=3)
measurements = qml.iterative_qpe(qml.RZ(2.0, wires=[0]), aux_wire=1, iters=3)
return qml.sample(measurements)
Expand All @@ -74,17 +79,37 @@ def circuit():
╚══════════════════════╩═════════════════════════║═══════╡ ├Sample[MCM]
╚═══════╡ ╰Sample[MCM]
"""
missing = []
if aux_wire == "unset" and ancilla == "unset":
missing.append("'aux_wire'")
if iters == "unset":
missing.append("'iters'")

if missing:
missing_args = " and ".join(missing)
raise TypeError(
f"iterative_qpe() missing {len(missing)} required positional argument(s): {missing_args}"
)

if ancilla != "unset":
warn(
"The 'ancilla' argument for qml.iterative_qpe has been deprecated. Please use the "
"'aux_wire' argument instead.",
qml.PennyLaneDeprecationWarning,
)
if aux_wire == "unset":
aux_wire = ancilla

measurements = []

for i in range(iters):
qml.Hadamard(wires=ancilla)
qml.ctrl(qml.pow(base, z=2 ** (iters - i - 1)), control=ancilla)
qml.Hadamard(wires=aux_wire)
qml.ctrl(qml.pow(base, z=2 ** (iters - i - 1)), control=aux_wire)

for ind, meas in enumerate(measurements):
qml.cond(meas, qml.PhaseShift)(-2.0 * np.pi / 2 ** (ind + 2), wires=ancilla)
qml.cond(meas, qml.PhaseShift)(-2.0 * np.pi / 2 ** (ind + 2), wires=aux_wire)

qml.Hadamard(wires=ancilla)
measurements.insert(0, qml.measure(wires=ancilla, reset=True))
qml.Hadamard(wires=aux_wire)
measurements.insert(0, qml.measure(wires=aux_wire, reset=True))

return measurements
12 changes: 12 additions & 0 deletions pennylane/shadows/transforms.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ def shadow_expval(tape: QuantumScript, H, k=1) -> tuple[QuantumScriptBatch, Post
See :func:`~.pennylane.shadow_expval` for more usage details.
.. warning::
``qml.shadows.shadow_expval`` is deprecated. Please use the :func:`~pennylane.shadow_expval`
measurement process in your circuits instead.
Args:
tape (QNode or QuantumTape or Callable): A quantum circuit.
H (:class:`~.pennylane.Observable` or list[:class:`~.pennylane.Observable`]): Observables
Expand Down Expand Up @@ -96,6 +101,13 @@ def circuit(x):
>>> qml.grad(circuit)(x)
-0.9323999999999998
"""

warnings.warn(
"qml.shadows.shadow_expval is deprecated. Instead, use the qml.shadow_expval "
"measurement process in your circuit.",
qml.PennyLaneDeprecationWarning,
)

tapes, _ = _replace_obs(tape, qml.shadow_expval, H, k=k)

def post_processing_fn(res):
Expand Down
12 changes: 12 additions & 0 deletions pennylane/templates/broadcast.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
``details`` section,
* add tests to parametrizations in :func:`test_templates_broadcast`.
"""
from warnings import warn

# pylint: disable-msg=too-many-branches,too-many-arguments,protected-access
import pennylane as qml
from pennylane.wires import Wires
Expand Down Expand Up @@ -212,6 +214,10 @@ def broadcast(unitary, wires, pattern, parameters=None, kwargs=None):
For more details, see *Usage Details* below.
.. warning::
``qml.broadcast`` has been deprecated. Please use ``for`` loops instead.
Args:
unitary (func): quantum gate or template
pattern (str): specifies the wire pattern of the broadcast
Expand Down Expand Up @@ -553,6 +559,12 @@ def circuit(pars):
# We deliberately disable iterating using enumerate here, since
# it causes a slowdown when iterating over TensorFlow variables.
# pylint: disable=consider-using-enumerate

warn(
"qml.broadcast is deprecated. Please use a for loop instead",
qml.PennyLaneDeprecationWarning,
)

wires = Wires(wires)
if kwargs is None:
kwargs = {}
Expand Down
3 changes: 2 additions & 1 deletion pennylane/templates/subroutines/arbitrary_unitary.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ class ArbitraryUnitary(Operation):
.. code-block:: python
def arbitrary_nearest_neighbour_interaction(weights, wires):
qml.broadcast(unitary=ArbitraryUnitary, pattern="double", wires=wires, parameters=weights)
for i, w in enumerate(range(0, len(wires) - 1, 2)):
ArbitraryUnitary(weights[i], wires=[w, w + 1])
Args:
weights (tensor_like): The angles of the Pauli word rotations, needs to have length :math:`4^n - 1`
Expand Down
2 changes: 1 addition & 1 deletion pennylane/templates/subroutines/qubitization.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def circuit():
# apply QPE
measurements = qml.iterative_qpe(
qml.Qubitization(H, control = [3,4]), ancilla = 5, iters = 3
qml.Qubitization(H, control = [3,4]), aux_wire = 5, iters = 3
)
return qml.probs(op = measurements)
Expand Down
36 changes: 33 additions & 3 deletions tests/ops/functions/test_iterative_qpe.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,36 @@
class TestIQPE:
"""Test to check that the iterative quantum phase estimation function works as expected."""

def test_ancilla_deprecation(self):
"""Test that the ancilla argument is deprecated and superceded by the aux_wire argument
if provided."""
aux_wire = 1
ancilla = 2

with pytest.warns(qml.PennyLaneDeprecationWarning, match="The 'ancilla' argument"):
meas1 = qml.iterative_qpe(qml.RZ(2.0, wires=0), ancilla=ancilla, iters=3)
meas2 = qml.iterative_qpe(
qml.RZ(2.0, wires=0), aux_wire=aux_wire, iters=3, ancilla=ancilla
)

assert all(m.wires == qml.wires.Wires(ancilla) for m in meas1)
assert all(m.wires == qml.wires.Wires(aux_wire) for m in meas2)

@pytest.mark.parametrize(
"args, n_missing, missing_args",
[
({"aux_wire": 1}, 1, "'iters'"),
({"ancilla": 1}, 1, "'iters'"),
({"iters": 1}, 1, "'aux_wire'"),
({}, 2, "'aux_wire' and 'iters'"),
],
)
def test_args_not_provided(self, args, n_missing, missing_args):
"""Test that the correct error is raised if there are missing arguments"""
err_msg = rf"iterative_qpe\(\) missing {n_missing} required positional argument\(s\): {missing_args}"
with pytest.raises(TypeError, match=err_msg):
_ = qml.iterative_qpe(qml.RZ(1.5, 0), **args)

@pytest.mark.parametrize("mcm_method", ["deferred", "tree-traversal"])
@pytest.mark.parametrize("phi", (1.0, 2.0, 3.0))
def test_compare_qpe(self, mcm_method, phi):
Expand All @@ -37,7 +67,7 @@ def circuit_iterative():
qml.PauliX(wires=[0])

# Iterative QPE
measurements = qml.iterative_qpe(qml.RZ(phi, wires=[0]), ancilla=[1], iters=3)
measurements = qml.iterative_qpe(qml.RZ(phi, wires=[0]), aux_wire=[1], iters=3)

return [qml.sample(op=meas) for meas in measurements]

Expand Down Expand Up @@ -206,7 +236,7 @@ def circuit_iterative():
qml.PauliX(wires=[0])

# Iterative QPE
measurements = qml.iterative_qpe(qml.RZ(phi, wires=[0]), ancilla=[1], iters=3)
measurements = qml.iterative_qpe(qml.RZ(phi, wires=[0]), aux_wire=[1], iters=3)

return [qml.probs(op=i) for i in measurements]

Expand Down Expand Up @@ -235,7 +265,7 @@ def circuit_iterative():
qml.PauliX(wires=[0])

# Iterative QPE
measurements = qml.iterative_qpe(qml.RZ(phi, wires=[0]), ancilla=[1], iters=3)
measurements = qml.iterative_qpe(qml.RZ(phi, wires=[0]), aux_wire=[1], iters=3)

return [qml.expval(op=i) for i in measurements]

Expand Down
Loading

0 comments on commit a40e3e7

Please sign in to comment.