From e7cf301653f3217c38122681e77e7511278d073a Mon Sep 17 00:00:00 2001 From: Mudit Pandey Date: Tue, 17 Sep 2024 16:29:24 -0400 Subject: [PATCH] Remove simplify argument from Hamiltonian and LinearCombination --- doc/development/deprecations.rst | 12 +- doc/releases/changelog-dev.md | 4 + pennylane/ops/op_math/linear_combination.py | 25 ---- pennylane/ops/qubit/hamiltonian.py | 24 ---- tests/ops/op_math/test_linear_combination.py | 123 ++++--------------- tests/ops/qubit/test_hamiltonian.py | 104 ++++------------ 6 files changed, 54 insertions(+), 238 deletions(-) diff --git a/doc/development/deprecations.rst b/doc/development/deprecations.rst index d67c9abf636..95504765d73 100644 --- a/doc/development/deprecations.rst +++ b/doc/development/deprecations.rst @@ -50,12 +50,6 @@ Pending deprecations - Deprecated in v0.38 - Will be removed in v0.39 -* 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``. @@ -92,6 +86,12 @@ functionality will explicitly raise a deprecation warning when used: Other deprecations ~~~~~~~~~~~~~~~~~~ +* 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 + * PennyLane Lightning and Catalyst will no longer support ``manylinux2014`` (GLIBC 2.17) compatibile Linux operating systems, and will be migrated to ``manylinux_2_28`` (GLIBC 2.28). See `pypa/manylinux `_ for additional details. - Last supported version of ``manylinux2014`` with v0.36 diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md index bbcf978442f..ed5142b6009 100644 --- a/doc/releases/changelog-dev.md +++ b/doc/releases/changelog-dev.md @@ -63,6 +63,10 @@

Breaking changes 💔

+* The `simplify` argument in `qml.Hamiltonian` and `qml.ops.LinearCombination` has been removed. + Instead, `qml.simplify()` can be called on the constructed operator. + [(#)]() + * 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) diff --git a/pennylane/ops/op_math/linear_combination.py b/pennylane/ops/op_math/linear_combination.py index 473a0253b60..c14975d1c3d 100644 --- a/pennylane/ops/op_math/linear_combination.py +++ b/pennylane/ops/op_math/linear_combination.py @@ -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. @@ -52,10 +49,6 @@ class LinearCombination(Sum): .. seealso:: `rustworkx.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 @@ -124,7 +117,6 @@ def __init__( self, coeffs, observables: list[Operator], - simplify=False, grouping_type=None, method="lf", _grouping_indices=None, @@ -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] diff --git a/pennylane/ops/qubit/hamiltonian.py b/pennylane/ops/qubit/hamiltonian.py index e369d5001e4..73e75bf76d8 100644 --- a/pennylane/ops/qubit/hamiltonian.py +++ b/pennylane/ops/qubit/hamiltonian.py @@ -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. @@ -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:: @@ -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", @@ -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( diff --git a/tests/ops/op_math/test_linear_combination.py b/tests/ops/op_math/test_linear_combination.py index 553427ce799..53b174e7741 100644 --- a/tests/ops/op_math/test_linear_combination.py +++ b/tests/ops/op_math/test_linear_combination.py @@ -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.""" @@ -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() @@ -1659,7 +1647,7 @@ 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, @@ -1670,20 +1658,6 @@ def circuit(): # 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""" @@ -1702,23 +1676,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) @@ -1783,23 +1747,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) @@ -1860,24 +1814,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) @@ -1938,22 +1881,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) @@ -2032,23 +1965,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 diff --git a/tests/ops/qubit/test_hamiltonian.py b/tests/ops/qubit/test_hamiltonian.py index 169988f8c80..f02bda4886f 100644 --- a/tests/ops/qubit/test_hamiltonian.py +++ b/tests/ops/qubit/test_hamiltonian.py @@ -703,15 +703,6 @@ def test_deprecation_with_new_opmath(recwarn): assert len(recwarn) == 0 -def test_deprecation_simplify_argument(): - """Test that a deprecation warning is raised if the simplify argument is True.""" - with pytest.warns( - qml.PennyLaneDeprecationWarning, - match="deprecated", - ): - _ = qml.ops.Hamiltonian([1.0], [qml.X(0)], simplify=True) - - @pytest.mark.usefixtures("use_legacy_opmath") class TestHamiltonian: """Test the Hamiltonian class""" @@ -1750,7 +1741,7 @@ def test_simplify_reduces_tape_parameters(self): def circuit(): qml.RY(0.1, wires=0) return qml.expval( - qml.Hamiltonian([1.0, 2.0], [qml.PauliX(1), qml.PauliX(1)], simplify=True) + qml.simplify(qml.Hamiltonian([1.0, 2.0], [qml.PauliX(1), qml.PauliX(1)])) ) with pytest.warns( @@ -1781,24 +1772,13 @@ def circuit(coeffs, param): qml.RX(param, wires=0) qml.RY(param, wires=0) return qml.expval( - qml.Hamiltonian( - coeffs, - [qml.PauliX(0), qml.PauliZ(0)], - simplify=simplify, - grouping_type=group, - ) + qml.simplify(qml.Hamiltonian(coeffs, [qml.X(0), qml.Z(0)], grouping_type=group)) + if simplify + else qml.Hamiltonian(coeffs, [qml.X(0), qml.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) @@ -1863,24 +1843,13 @@ def circuit(coeffs, param): qml.RX(param, wires=0) qml.RY(param, wires=0) return qml.expval( - qml.Hamiltonian( - coeffs, - [qml.PauliX(0), qml.PauliZ(0)], - simplify=simplify, - grouping_type=group, - ) + qml.simplify(qml.Hamiltonian(coeffs, [qml.X(0), qml.Z(0)], grouping_type=group)) + if simplify + else qml.ops.Hamiltonian(coeffs, [qml.X(0), qml.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) @@ -1941,23 +1910,13 @@ def circuit(coeffs, param): qml.RX(param, wires=0) qml.RY(param, wires=0) return qml.expval( - qml.Hamiltonian( - coeffs, - [qml.PauliX(0), qml.PauliZ(0)], - simplify=simplify, - grouping_type=group, - ) + qml.simplify(qml.Hamiltonian(coeffs, [qml.X(0), qml.Z(0)], grouping_type=group)) + if simplify + else qml.ops.Hamiltonian(coeffs, [qml.X(0), qml.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) @@ -2017,23 +1976,12 @@ def circuit(coeffs, param): qml.RX(param, wires=0) qml.RY(param, wires=0) return qml.expval( - qml.Hamiltonian( - coeffs, - [qml.PauliX(0), qml.PauliZ(0)], - simplify=simplify, - grouping_type=group, - ) + qml.simplify(qml.Hamiltonian(coeffs, [qml.X(0), qml.Z(0)], grouping_type=group)) + if simplify + else qml.ops.Hamiltonian(coeffs, [qml.X(0), qml.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) @@ -2112,23 +2060,13 @@ def circuit(coeffs, param): qml.RX(param, wires=0) qml.RY(param, wires=0) return qml.expval( - qml.Hamiltonian( - coeffs, - [qml.PauliX(0), qml.PauliZ(0)], - simplify=simplify, - grouping_type=group, - ) + qml.simplify(qml.Hamiltonian(coeffs, [qml.X(0), qml.Z(0)], grouping_type=group)) + if simplify + else qml.ops.Hamiltonian(coeffs, [qml.X(0), qml.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])