Skip to content

Commit

Permalink
Deprecate collections module (PennyLaneAI#3686)
Browse files Browse the repository at this point in the history
* 🎨 style (collections): Deprecate module.

* ✏️ chore (changelog): Add changelog entry.

* 🎨 style (collections): codefactor.

* 🔧 refactor (dot): Replace qml.ops.dot by qml.dot.

* 📝 docs (dot): Fix example.

* 🔧 refactor (collections): Update deprecation warnings.

* 📝 docs (dot): Fix sphinx.

* 🧪 tests (dot): Fix path.

* 🧪 tests (dot): Fix path.

* 📝 docs (dot): Fix path.

* 🧪 tests (dot): Fix path.

* 🎨 style (dot): Redirect to qml.collections.dot if input is QNodeCollection.

* 🧪 tests (dot): Test warning.

* 🧪 tests (collections): Fix tests.

* ✏️ chore (changelog): Add changelog entry.

* ⏪ revert (dot): Revert changes.

* 🎨 style (dot): Use qml.

* ✏️ chore (changelog): Stop using qml.ops.dot in changelog.

* ⏪ revert (init): Revert changes.

* 🔧 refactor (sum): Change qml.op_sum to qml.sum.

* ✏️ chore (changelog): Add changelog entry.

* 🧪 tests (sum): Fix.

* 📝 docs (sum): Add to deprecations page.

* 📝 docs (sum): Update docstring.

* Update doc/releases/changelog-dev.md

* Update doc/development/deprecations.rst

Co-authored-by: Mudit Pandey <[email protected]>

* 🎨 style (dot): Change warning message.

* Update pennylane/pulse/parametrized_evolution.py

Co-authored-by: Mudit Pandey <[email protected]>

* Update pennylane/pulse/parametrized_evolution.py

---------

Co-authored-by: Mudit Pandey <[email protected]>
  • Loading branch information
AlbertMitjans and mudit2812 authored Jan 27, 2023
1 parent 146f3d5 commit eb605de
Show file tree
Hide file tree
Showing 45 changed files with 374 additions and 267 deletions.
10 changes: 10 additions & 0 deletions doc/development/deprecations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,16 @@ Pending deprecations
- Deprecated in v0.28
- Will be removed in v0.29

* The ``collections`` module has been deprecated.

- Deprecated in v0.29
- Will be removed in v0.31

* ``qml.op_sum``` is deprecated. Users should use ``qml.sum`` instead.

- Deprecated in v0.29.
- Will be removed in v0.31.

Completed deprecation cycles
----------------------------

Expand Down
8 changes: 4 additions & 4 deletions doc/introduction/compiling_circuits.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ RX(0.09999999999999964, wires=[0])
RX(11.336370614359172, wires=[0])
>>> qml.simplify(qml.ops.Pow(qml.RX(1, 0), 3))
RX(3.0, wires=[0])
>>> qml.simplify(qml.op_sum(qml.PauliY(3), qml.PauliY(3)))
>>> qml.simplify(qml.sum(qml.PauliY(3), qml.PauliY(3)))
2*(PauliY(wires=[3]))
>>> qml.simplify(qml.RX(1, 0) @ qml.RX(1, 0))
RX(2.0, wires=[0])
Expand All @@ -53,19 +53,19 @@ Several simplifications steps are happening here. First of all, the nested produ

.. code-block:: python
qml.prod(qml.PauliX(0), qml.op_sum(qml.RX(1, 0), qml.PauliX(0)), qml.RX(1, 0))
qml.prod(qml.PauliX(0), qml.sum(qml.RX(1, 0), qml.PauliX(0)), qml.RX(1, 0))
Then the product of sums is transformed into a sum of products:

.. code-block:: python
qml.op_sum(qml.prod(qml.PauliX(0), qml.RX(1, 0), qml.RX(1, 0)), qml.prod(qml.PauliX(0), qml.PauliX(0), qml.RX(1, 0)))
qml.sum(qml.prod(qml.PauliX(0), qml.RX(1, 0), qml.RX(1, 0)), qml.prod(qml.PauliX(0), qml.PauliX(0), qml.RX(1, 0)))
And finally like terms in the obtained products are grouped together, removing all identities:

.. code-block:: python
qml.op_sum(qml.prod(qml.PauliX(0), qml.RX(2, 0)), qml.RX(1, 0))
qml.sum(qml.prod(qml.PauliX(0), qml.RX(2, 0)), qml.RX(1, 0))
As mentioned earlier we can also simplify QNode objects to, for example, group rotation gates:

Expand Down
6 changes: 3 additions & 3 deletions doc/introduction/operations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -52,19 +52,19 @@ Operator to Operator functions
~pennylane.ctrl
~pennylane.cond
~pennylane.exp
~pennylane.op_sum
~pennylane.sum
~pennylane.pow
~pennylane.prod
~pennylane.s_prod
~pennylane.generator
~pennylane.map_wires
~pennylane.ops.dot
~pennylane.dot
~pennylane.evolve

These operator functions act on operators to produce new operators.

>>> op = qml.prod(qml.PauliX(0), qml.PauliZ(1))
>>> op = qml.op_sum(qml.Hadamard(0), op)
>>> op = qml.sum(qml.Hadamard(0), op)
>>> op = qml.s_prod(1.2, op)
>>> op
1.2*(Hadamard(wires=[0]) + (PauliX(wires=[0]) @ PauliZ(wires=[1])))
Expand Down
44 changes: 26 additions & 18 deletions doc/releases/changelog-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
* Parameterized Hamiltonians can now be created with the addition of `ParametrizedHamiltonian`.
[(#3617)](https://github.com/PennyLaneAI/pennylane/pull/3617)

A `ParametrizedHamiltonian` holds information representing a linear combination of operators
with parametrized coefficents. The `ParametrizedHamiltonian` can be passed parameters to create the operator for
A `ParametrizedHamiltonian` holds information representing a linear combination of operators
with parametrized coefficents. The `ParametrizedHamiltonian` can be passed parameters to create the operator for
the specified parameters.

```pycon
Expand All @@ -25,6 +25,7 @@

H = 2 * XX + f1 * YY + f2 * ZZ
```

```pycon
>>> H
ParametrizedHamiltonian: terms=3
Expand All @@ -38,7 +39,7 @@
```pycon
>>> coeffs = [2, f1, f2]
>>> ops = [XX, YY, ZZ]
>>> H = qml.ops.dot(coeffs, ops)
>>> H = qml.dot(coeffs, ops)
```

* A `ParametrizedHamiltonian` can be time-evolved by using `ParametrizedEvolution`.
Expand All @@ -47,18 +48,19 @@
* A new function called `qml.evolve` has been added that returns the evolution of an operator or a `ParametrizedHamiltonian`.
[(#3617)](https://github.com/PennyLaneAI/pennylane/pull/3617)

* A new function called `qml.ops.dot` has been added to compute the dot product between a vector and a list of operators.
* A new function `dot` has been added to compute the dot product between a vector and a list of operators. `qml.dot` will now target this new function.
[(#3586)](https://github.com/PennyLaneAI/pennylane/pull/3586)

```pycon
>>> coeffs = np.array([1.1, 2.2])
>>> ops = [qml.PauliX(0), qml.PauliY(0)]
>>> qml.ops.dot(coeffs, ops)
>>> qml.dot(coeffs, ops)
(1.1*(PauliX(wires=[0]))) + (2.2*(PauliY(wires=[0])))
>>> qml.ops.dot(coeffs, ops, pauli=True)
>>> qml.dot(coeffs, ops, pauli=True)
1.1 * X(0)
+ 2.2 * Y(0)
```

[(#3586)](https://github.com/PennyLaneAI/pennylane/pull/3586)

<h4>Always differentiable 📈</h4>
Expand Down Expand Up @@ -241,10 +243,9 @@
4: ─────────────────╰RY(0.81)─╰SWAP─────────────────╰RY(0.06)─╰SWAP─────────────────┤ State
```


* Added `pwc` as a convenience function for defining a `ParametrizedHamiltonian`.
This function can be used to create a callable coefficient by setting
the timespan over which the function should be non-zero. The resulting callable
This function can be used to create a callable coefficient by setting
the timespan over which the function should be non-zero. The resulting callable
can be passed an array of parameters and a time.
[(#3645)](https://github.com/PennyLaneAI/pennylane/pull/3645)

Expand All @@ -253,8 +254,9 @@
>>> f = pwc(timespan)
>>> f * qml.PauliX(0)
ParametrizedHamiltonian: terms=1
```
The `params` array will be used as bin values evenly distributed over the timespan,
```

The `params` array will be used as bin values evenly distributed over the timespan,
and the parameter `t` will determine which of the bins is returned.

```pycon
Expand All @@ -266,15 +268,16 @@

* Added `pwc_from_function` as a decorator for defining a `ParametrizedHamiltonian`.
This function can be used to decorate a function and create a piecewise constant
approximation of it.
approximation of it.
[(#3645)](https://github.com/PennyLaneAI/pennylane/pull/3645)

```pycon
>>> @pwc_from_function(t=(2, 4), num_bins=10)
... def f1(p, t):
... return p * t
```
The resulting function approximates the same of `p**2 * t` on the interval `t=(2, 4)`

The resulting function approximates the same of `p**2 * t` on the interval `t=(2, 4)`
in 10 bins, and returns zero outside the interval.

```pycon
Expand All @@ -289,7 +292,6 @@
DeviceArray(0., dtype=float32)
```


<h3>Improvements</h3>

* `qml.purity` is added as a measurement process for purity
Expand Down Expand Up @@ -346,13 +348,13 @@
* Lazy-loading in the `Dataset.read()` method is more universally supported.
[(#3605)](https://github.com/PennyLaneAI/pennylane/pull/3605)

* Implemented the XYX single-qubit unitary decomposition.
[(#3628)](https://github.com/PennyLaneAI/pennylane/pull/3628)
* Implemented the XYX single-qubit unitary decomposition.
[(#3628)](https://github.com/PennyLaneAI/pennylane/pull/3628)

* `Sum` and `Prod` operations now have broadcasted operands.
[(#3611)](https://github.com/PennyLaneAI/pennylane/pull/3611)

* `qml.ops.dot` is now compatible with JAX-JIT.
* `qml.dot` is now compatible with JAX-JIT.
[(#3636)](https://github.com/PennyLaneAI/pennylane/pull/3636)

* All dunder methods now return `NotImplemented`, allowing the right dunder method (e.g. `__radd__`)
Expand Down Expand Up @@ -381,7 +383,7 @@
* `Operator.inv()` and the `Operator.inverse` setter have been removed. Please use `qml.adjoint` or `qml.pow` instead.
[(#3618)](https://github.com/PennyLaneAI/pennylane/pull/3618)

For example, instead of
For example, instead of

```pycon
>>> qml.PauliX(0).inv()
Expand Down Expand Up @@ -412,6 +414,12 @@

<h3>Deprecations</h3>

* Deprecate the `collections` module.
[(#3686)](https://github.com/PennyLaneAI/pennylane/pull/3686)

* `qml.op_sum` has been deprecated. Users should use `qml.sum` instead.
[(#3686)](https://github.com/PennyLaneAI/pennylane/pull/3686)

<h3>Documentation</h3>

* Organizes the module for documentation for ``operation``.
Expand Down
4 changes: 2 additions & 2 deletions pennylane/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
shadow_expval,
)
from pennylane.ops import *
from pennylane.ops import adjoint, ctrl, exp, op_sum, pow, prod, s_prod
from pennylane.ops import adjoint, ctrl, exp, sum, pow, prod, s_prod, op_sum
from pennylane.templates import broadcast, layer
from pennylane.templates.embeddings import *
from pennylane.templates.layers import *
Expand Down Expand Up @@ -108,7 +108,7 @@
import pennylane.pulse

# collections needs to be imported after all other pennylane imports
from .collections import QNodeCollection, dot, map, sum
from .collections import QNodeCollection, map
import pennylane.gradients # pylint:disable=wrong-import-order
import pennylane.qinfo # pylint:disable=wrong-import-order
from pennylane.interfaces import execute # pylint:disable=wrong-import-order
Expand Down
3 changes: 3 additions & 0 deletions pennylane/collections/apply.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"""
Contains the apply function
"""
import warnings


# pylint:disable=unnecessary-lambda-assignment
Expand Down Expand Up @@ -48,6 +49,8 @@ def apply(func, qnode_collection):
>>> cost(x)
tensor(0.9092, dtype=torch.float64, grad_fn=<SumBackward0>)
"""
warnings.warn("The apply function is deprecated and it will be removed soon.", UserWarning)

new_func = lambda params, **kwargs: func(qnode_collection(params, **kwargs))
new_func.interface = qnode_collection.interface
return new_func
6 changes: 6 additions & 0 deletions pennylane/collections/dot.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
Contains functions to implement the dot product between QNode collections
"""
# pylint: disable=too-many-arguments,import-outside-toplevel,unnecessary-lambda-assignment
import warnings


def _get_dot_func(interface, x=None):
Expand Down Expand Up @@ -123,6 +124,11 @@ def dot(x, y):
>>> cost(x)
tensor(-0.2183, dtype=torch.float64, grad_fn=<DotBackward>)
"""
warnings.warn(
"The dot function of the collections module is deprecated and it will be removed soon.",
UserWarning,
)

if hasattr(x, "interface") and hasattr(y, "interface"):

if x.interface != y.interface:
Expand Down
5 changes: 4 additions & 1 deletion pennylane/collections/map.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
"""
Contains the map function, for mapping templates over observables and devices.
"""
import warnings

# pylint: disable=too-many-arguments
from collections.abc import Sequence

Expand All @@ -22,7 +24,6 @@

from .qnode_collection import QNodeCollection


MEASURE_MAP = {"expval": qml.expval, "var": qml.var, "sample": qml.sample}


Expand Down Expand Up @@ -103,6 +104,8 @@ def my_template(params, wires, **kwargs):
>>> qnodes(params)
array([-0.06154835 0.99280864])
"""
warnings.warn("The map function is deprecated and it will be removed soon.", UserWarning)

if not callable(template):
raise ValueError("Could not create QNodes. The template is not a callable function.")

Expand Down
7 changes: 6 additions & 1 deletion pennylane/collections/qnode_collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@
"""
Contains the QNodeCollection class.
"""
import warnings

# pylint: disable=too-many-arguments,import-outside-toplevel
from collections.abc import Sequence
import warnings


class QNodeCollection(Sequence):
Expand Down Expand Up @@ -159,6 +160,10 @@ def qnode2(x, y):
"""

def __init__(self, qnodes=None):
warnings.warn(
"The QNodeCollection class is deprecated and it will be removed soon.", UserWarning
)

self.qnodes = []
self.extend(qnodes or [])

Expand Down
7 changes: 7 additions & 0 deletions pennylane/collections/sum.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
"""
# pylint: disable=too-many-arguments,import-outside-toplevel

import warnings

from .apply import apply


Expand Down Expand Up @@ -48,6 +50,11 @@ def sum(x):
>>> cost(x)
tensor(0.9177, dtype=torch.float64)
"""
warnings.warn(
"The sum function of the collections module is deprecated and it will be removed soon.",
UserWarning,
)

if hasattr(x, "interface") and x.interface is not None:
if x.interface == "tf":
import tensorflow as tf
Expand Down
4 changes: 2 additions & 2 deletions pennylane/operation.py
Original file line number Diff line number Diff line change
Expand Up @@ -1406,7 +1406,7 @@ def simplify(self) -> "Operator": # pylint: disable=unused-argument
def __add__(self, other):
"""The addition operation of Operator-Operator objects and Operator-scalar."""
if isinstance(other, Operator):
return qml.op_sum(self, other)
return qml.sum(self, other)
if other == 0:
return self
if isinstance(other, qml.pulse.ParametrizedHamiltonian):
Expand All @@ -1415,7 +1415,7 @@ def __add__(self, other):
if (backend == "builtins" and isinstance(other, numbers.Number)) or (
backend in SUPPORTED_INTERFACES and qml.math.shape(other) == ()
):
return qml.op_sum(self, qml.s_prod(scalar=other, operator=qml.Identity(self.wires)))
return qml.sum(self, qml.s_prod(scalar=other, operator=qml.Identity(self.wires)))
return NotImplemented

__radd__ = __add__
Expand Down
4 changes: 3 additions & 1 deletion pennylane/ops/functions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,17 @@
~matrix
~simplify
~evolve
~dot
"""
from .dot import dot
from .eigvals import eigvals
from .equal import equal
from .evolve import evolve
from .generator import generator
from .is_commuting import is_commuting
from .is_hermitian import is_hermitian
from .is_unitary import is_unitary
from .map_wires import map_wires
from .matrix import matrix
from .simplify import simplify
from .evolve import evolve
Loading

0 comments on commit eb605de

Please sign in to comment.