Skip to content

Commit

Permalink
Remove simplify argument from Hamiltonian and LinearCombination (
Browse files Browse the repository at this point in the history
…#6279)

As name says. [sc-72003]
  • Loading branch information
mudit2812 authored Sep 18, 2024
1 parent 569c834 commit 68fd307
Show file tree
Hide file tree
Showing 7 changed files with 59 additions and 251 deletions.
12 changes: 6 additions & 6 deletions doc/development/deprecations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,6 @@ Pending deprecations
- Deprecated in v0.39
- Will be removed in v0.40

* The ``simplify`` argument in ``qml.Hamiltonian`` and ``qml.ops.LinearCombination`` is deprecated.
Instead, ``qml.simplify()`` can be called on the constructed operator.

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

* The ``QubitStateVector`` template is deprecated.
Instead, use ``StatePrep``.

Expand Down Expand Up @@ -101,6 +95,12 @@ Other deprecations
Completed deprecation cycles
----------------------------

* The ``simplify`` argument in ``qml.Hamiltonian`` and ``qml.ops.LinearCombination`` has been removed.
Instead, ``qml.simplify()`` can be called on the constructed operator.

- Deprecated in v0.37
- Removed in v0.39

* The ``decomp_depth`` argument in ``qml.device`` is removed.

- Deprecated in v0.38
Expand Down
6 changes: 3 additions & 3 deletions doc/news/new_opmath.rst
Original file line number Diff line number Diff line change
Expand Up @@ -245,10 +245,10 @@ To help identify a fix, select the option below that describes your situation.
>>> qml.Hamiltonian([0.5], [X(0) @ X(1)])
0.5 * (X(0) @ X(1))

The API of :class:`~.ops.op_math.LinearCombination` is identical to that of :class:`~.Hamiltonian`. We can group observables or simplify upon initialization.
The API of :class:`~.ops.op_math.LinearCombination` is identical to that of :class:`~.Hamiltonian`. We can group observables upon initialization.

>>> H1 = qml.Hamiltonian([0.5, 0.5, 0.5], [X(0) @ X(1), X(0), Y(0)], grouping_type="qwc", simplify=True)
>>> H2 = qml.ops.LinearCombination([0.5, 0.5, 0.5], [X(0) @ X(1), X(0), Y(0)], grouping_type="qwc", simplify=True)
>>> H1 = qml.Hamiltonian([0.5, 0.5, 0.5], [X(0) @ X(1), X(0), Y(0)], grouping_type="qwc")
>>> H2 = qml.ops.LinearCombination([0.5, 0.5, 0.5], [X(0) @ X(1), X(0), Y(0)], grouping_type="qwc")
>>> H1 == H2
True

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

<h3>Breaking changes 💔</h3>

* The `simplify` argument in `qml.Hamiltonian` and `qml.ops.LinearCombination` has been removed.
Instead, `qml.simplify()` can be called on the constructed operator.
[(#6279)](https://github.com/PennyLaneAI/pennylane/pull/6279)

* The functions `qml.qinfo.classical_fisher` and `qml.qinfo.quantum_fisher` have been removed and migrated to the `qml.gradients`
module. Therefore, `qml.gradients.classical_fisher` and `qml.gradients.quantum_fisher` should be used instead.
[(#5911)](https://github.com/PennyLaneAI/pennylane/pull/5911)
Expand Down
25 changes: 0 additions & 25 deletions pennylane/ops/op_math/linear_combination.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,6 @@ class LinearCombination(Sum):
Args:
coeffs (tensor_like): coefficients of the ``LinearCombination`` expression
observables (Iterable[Observable]): observables in the ``LinearCombination`` expression, of same length as ``coeffs``
simplify (bool): Specifies whether the ``LinearCombination`` is simplified upon initialization
(like-terms are combined). The default value is `False`. Note that ``coeffs`` cannot
be differentiated when using the ``'torch'`` interface and ``simplify=True``. Use of this argument is deprecated.
grouping_type (str): If not ``None``, compute and store information on how to group commuting
observables upon initialization. This information may be accessed when a :class:`~.QNode` containing this
``LinearCombination`` is executed on devices. The string refers to the type of binary relation between Pauli words.
Expand All @@ -52,10 +49,6 @@ class LinearCombination(Sum):
.. seealso:: `rustworkx.ColoringStrategy <https://www.rustworkx.org/apiref/rustworkx.ColoringStrategy.html#coloringstrategy>`_
for more information on the ``('lf', 'dsatur', 'gis')`` strategies.
.. warning::
The ``simplify`` argument is deprecated and will be removed in a future release.
Instead, you can call ``qml.simplify`` on the constructed operator.
**Example:**
A ``LinearCombination`` can be created by simply passing the list of coefficients
Expand Down Expand Up @@ -124,7 +117,6 @@ def __init__(
self,
coeffs,
observables: list[Operator],
simplify=False,
grouping_type=None,
method="lf",
_grouping_indices=None,
Expand All @@ -143,23 +135,6 @@ def __init__(
if _pauli_rep is None:
_pauli_rep = self._build_pauli_rep_static(coeffs, observables)

if simplify:

warnings.warn(
"The simplify argument in qml.Hamiltonian and qml.ops.LinearCombination is deprecated. "
"Instead, you can call qml.simplify on the constructed operator.",
qml.PennyLaneDeprecationWarning,
)

# simplify upon initialization changes ops such that they wouldnt be removed in self.queue() anymore
if qml.QueuingManager.recording():
for o in observables:
qml.QueuingManager.remove(o)

coeffs, observables, _pauli_rep = self._simplify_coeffs_ops(
coeffs, observables, _pauli_rep
)

self._coeffs = coeffs

self._ops = [convert_to_opmath(op) for op in observables]
Expand Down
24 changes: 0 additions & 24 deletions pennylane/ops/qubit/hamiltonian.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,6 @@ class Hamiltonian(Observable):
Args:
coeffs (tensor_like): coefficients of the Hamiltonian expression
observables (Iterable[Observable]): observables in the Hamiltonian expression, of same length as coeffs
simplify (bool): Specifies whether the Hamiltonian is simplified upon initialization
(like-terms are combined). The default value is `False`. Use of this argument is deprecated.
grouping_type (str): If not None, compute and store information on how to group commuting
observables upon initialization. This information may be accessed when QNodes containing this
Hamiltonian are executed on devices. The string refers to the type of binary relation between Pauli words.
Expand All @@ -91,10 +89,6 @@ class Hamiltonian(Observable):
can be ``'lf'`` (Largest First) or ``'rlf'`` (Recursive Largest First). Ignored if ``grouping_type=None``.
id (str): name to be assigned to this Hamiltonian instance
.. warning::
The ``simplify`` argument is deprecated and will be removed in a future release.
Instead, you can call ``qml.simplify`` on the constructed operator.
**Example:**
.. note::
Expand Down Expand Up @@ -254,7 +248,6 @@ def __init__(
self,
coeffs: TensorLike,
observables: Iterable[Observable],
simplify: bool = False,
grouping_type: Literal[None, "qwc", "commuting", "anticommuting"] = None,
_grouping_indices: Optional[list[list[int]]] = None,
method: Literal["lf", "rlf"] = "rlf",
Expand Down Expand Up @@ -293,23 +286,6 @@ def __init__(
# commuting observables, since recomputation is costly
self._grouping_indices = _grouping_indices

if simplify:

warn(
"The simplify argument in qml.Hamiltonian and qml.ops.LinearCombination is deprecated. "
"Instead, you can call qml.simplify on the constructed operator.",
qml.PennyLaneDeprecationWarning,
)

# simplify upon initialization changes ops such that they wouldnt be
# removed in self.queue() anymore, removing them here manually.
if qml.QueuingManager.recording():
for o in observables:
qml.QueuingManager.remove(o)

with qml.QueuingManager.stop_recording():
self.simplify()

if grouping_type is not None:
with qml.QueuingManager.stop_recording():
self._grouping_indices = _compute_grouping_indices(
Expand Down
129 changes: 24 additions & 105 deletions tests/ops/op_math/test_linear_combination.py
Original file line number Diff line number Diff line change
Expand Up @@ -580,14 +580,6 @@ def circuit2(param):
class TestLinearCombination:
"""Test the LinearCombination class"""

def test_deprecation_simplify_argument(self):
"""Test that a deprecation warning is raised if the simplify argument is True."""
with pytest.warns(
qml.PennyLaneDeprecationWarning,
match="deprecated",
):
_ = qml.ops.LinearCombination([1.0], [qml.X(0)], simplify=True)

def test_error_if_observables_operator(self):
"""Test thatt an error is raised if an operator is provided to observables."""

Expand All @@ -613,13 +605,9 @@ def test_error_if_observables_operator(self):
def test_pauli_rep(self, coeffs, ops, true_pauli, simplify):
"""Test the pauli rep is correctly constructed"""
if simplify:
with pytest.warns(
qml.PennyLaneDeprecationWarning,
match="deprecated",
):
H = qml.ops.LinearCombination(coeffs, ops, simplify=simplify)
H = qml.ops.LinearCombination(coeffs, ops).simplify()
else:
H = qml.ops.LinearCombination(coeffs, ops, simplify=simplify)
H = qml.ops.LinearCombination(coeffs, ops)
pr = H.pauli_rep
if simplify:
pr.simplify()
Expand Down Expand Up @@ -1659,31 +1647,13 @@ def test_simplify_reduces_tape_parameters(self):
@qml.qnode(device)
def circuit():
qml.RY(0.1, wires=0)
return qml.expval(qml.ops.LinearCombination([1.0, 2.0], [X(1), X(1)], simplify=True))
return qml.expval(qml.simplify(qml.ops.LinearCombination([1.0, 2.0], [X(1), X(1)])))

with pytest.warns(
qml.PennyLaneDeprecationWarning,
match="deprecated",
):
circuit()
circuit()
pars = circuit.qtape.get_parameters(trainable_only=False)
# simplify worked and added 1. and 2.
assert pars == [0.1, 3.0]

@pytest.mark.usefixtures("use_legacy_and_new_opmath")
def test_queuing_behaviour(self):
"""Tests that the base observables are correctly dequeued with simplify=True"""

with qml.queuing.AnnotatedQueue() as q:
with pytest.warns(
qml.PennyLaneDeprecationWarning,
match="deprecated",
):
obs = qml.Hamiltonian([1, 1, 1], [qml.X(0), qml.X(0), qml.Z(0)], simplify=True)

assert len(q) == 1
assert q.queue[0] == obs


class TestLinearCombinationDifferentiation:
"""Test that the LinearCombination coefficients are differentiable"""
Expand All @@ -1702,23 +1672,13 @@ def circuit(coeffs, param):
qml.RX(param, wires=0)
qml.RY(param, wires=0)
return qml.expval(
qml.ops.LinearCombination(
coeffs,
[X(0), Z(0)],
simplify=simplify,
grouping_type=group,
)
qml.simplify(qml.ops.LinearCombination(coeffs, [X(0), Z(0)], grouping_type=group))
if simplify
else qml.ops.LinearCombination(coeffs, [X(0), Z(0)], grouping_type=group)
)

grad_fn = qml.grad(circuit)
if simplify:
with pytest.warns(
qml.PennyLaneDeprecationWarning,
match="deprecated",
):
grad = grad_fn(coeffs, param)
else:
grad = grad_fn(coeffs, param)
grad = grad_fn(coeffs, param)

# differentiating a cost that combines circuits with
# measurements expval(Pauli)
Expand Down Expand Up @@ -1783,23 +1743,13 @@ def circuit(coeffs, param):
qml.RX(param, wires=0)
qml.RY(param, wires=0)
return qml.expval(
qml.ops.LinearCombination(
coeffs,
[X(0), Z(0)],
simplify=simplify,
grouping_type=group,
)
qml.simplify(qml.ops.LinearCombination(coeffs, [X(0), Z(0)], grouping_type=group))
if simplify
else qml.ops.LinearCombination(coeffs, [X(0), Z(0)], grouping_type=group)
)

grad_fn = qml.grad(circuit)
if simplify:
with pytest.warns(
qml.PennyLaneDeprecationWarning,
match="deprecated",
):
grad = grad_fn(coeffs, param)
else:
grad = grad_fn(coeffs, param)
grad = grad_fn(coeffs, param)

# differentiating a cost that combines circuits with
# measurements expval(Pauli)
Expand Down Expand Up @@ -1860,24 +1810,13 @@ def circuit(coeffs, param):
qml.RX(param, wires=0)
qml.RY(param, wires=0)
return qml.expval(
qml.ops.LinearCombination(
coeffs,
[X(0), Z(0)],
simplify=simplify,
grouping_type=group,
)
qml.simplify(qml.ops.LinearCombination(coeffs, [X(0), Z(0)], grouping_type=group))
if simplify
else qml.ops.LinearCombination(coeffs, [X(0), Z(0)], grouping_type=group)
)

grad_fn = jax.grad(circuit)

if simplify:
with pytest.warns(
qml.PennyLaneDeprecationWarning,
match="deprecated",
):
grad = grad_fn(coeffs, param)
else:
grad = grad_fn(coeffs, param)
grad = grad_fn(coeffs, param)

# differentiating a cost that combines circuits with
# measurements expval(Pauli)
Expand Down Expand Up @@ -1938,22 +1877,12 @@ def circuit(coeffs, param):
qml.RX(param, wires=0)
qml.RY(param, wires=0)
return qml.expval(
qml.ops.LinearCombination(
coeffs,
[X(0), Z(0)],
simplify=simplify,
grouping_type=group,
)
qml.simplify(qml.ops.LinearCombination(coeffs, [X(0), Z(0)], grouping_type=group))
if simplify
else qml.ops.LinearCombination(coeffs, [X(0), Z(0)], grouping_type=group)
)

if simplify:
with pytest.warns(
qml.PennyLaneDeprecationWarning,
match="deprecated",
):
res = circuit(coeffs, param)
else:
res = circuit(coeffs, param)
res = circuit(coeffs, param)
res.backward() # pylint:disable=no-member
grad = (coeffs.grad, param.grad)

Expand Down Expand Up @@ -2032,23 +1961,13 @@ def circuit(coeffs, param):
qml.RX(param, wires=0)
qml.RY(param, wires=0)
return qml.expval(
qml.ops.LinearCombination(
coeffs,
[X(0), Z(0)],
simplify=simplify,
grouping_type=group,
)
qml.simplify(qml.ops.LinearCombination(coeffs, [X(0), Z(0)], grouping_type=group))
if simplify
else qml.ops.LinearCombination(coeffs, [X(0), Z(0)], grouping_type=group)
)

with tf.GradientTape() as tape:
if simplify:
with pytest.warns(
qml.PennyLaneDeprecationWarning,
match="deprecated",
):
res = circuit(coeffs, param)
else:
res = circuit(coeffs, param)
res = circuit(coeffs, param)
grad = tape.gradient(res, [coeffs, param])

# differentiating a cost that combines circuits with
Expand Down
Loading

0 comments on commit 68fd307

Please sign in to comment.