From 9404bd563a3e7f6b5b71c0a26278258b722c4c66 Mon Sep 17 00:00:00 2001 From: andrijapau Date: Wed, 6 Nov 2024 09:36:47 -0500 Subject: [PATCH 1/5] initial removals --- doc/development/deprecations.rst | 22 +++++++++---------- doc/releases/changelog-dev.md | 4 ++++ pennylane/transforms/compile.py | 16 +------------- .../decompositions/clifford_t_transform.py | 22 +------------------ .../core/test_transform_dispatcher.py | 16 ++++---------- .../transforms/core/test_transform_program.py | 8 ++----- tests/transforms/test_cliffordt_transform.py | 17 +------------- tests/transforms/test_compile.py | 13 ----------- 8 files changed, 24 insertions(+), 94 deletions(-) diff --git a/doc/development/deprecations.rst b/doc/development/deprecations.rst index bcf937dd6bd..479c8c6cf53 100644 --- a/doc/development/deprecations.rst +++ b/doc/development/deprecations.rst @@ -9,17 +9,6 @@ deprecations are listed below. Pending deprecations -------------------- -* The ``max_expansion`` argument for :func:`~pennylane.transforms.decompositions.clifford_t_decomposition` - has been deprecated. - - - Deprecated in v0.39 - - Will be removed in v0.40 - -* The ``expand_depth`` argument for :func:`~pennylane.transforms.compile` has been deprecated. - - - Deprecated in v0.39 - - Will be removed in v0.40 - * The ``'ancilla'`` argument for :func:`~pennylane.iterative_qpe` has been deprecated. Instead, use the ``'aux_wire'`` argument. @@ -131,6 +120,17 @@ Other deprecations Completed deprecation cycles ---------------------------- +* The ``max_expansion`` argument for :func:`~pennylane.transforms.decompositions.clifford_t_decomposition` + has been removed. + + - Deprecated in v0.39 + - Removed in v0.40 + +* The ``expand_depth`` argument for :func:`~pennylane.transforms.compile` has been removed. + + - Deprecated in v0.39 + - Removed in v0.40 + * The ``simplify`` argument in ``qml.Hamiltonian`` and ``qml.ops.LinearCombination`` has been removed. Instead, ``qml.simplify()`` can be called on the constructed operator. diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md index 227a622e833..064c87164b3 100644 --- a/doc/releases/changelog-dev.md +++ b/doc/releases/changelog-dev.md @@ -28,6 +28,10 @@

Breaking changes 💔

+* The ``max_expansion`` argument for :func:`~pennylane.transforms.decompositions.clifford_t_decomposition` has been removed. + +* The ``expand_depth`` argument for :func:`~pennylane.transforms.compile` has been removed. +

Deprecations 👋

Documentation 📝

diff --git a/pennylane/transforms/compile.py b/pennylane/transforms/compile.py index 4be2d9238cd..c14d9e386b5 100644 --- a/pennylane/transforms/compile.py +++ b/pennylane/transforms/compile.py @@ -12,8 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. """Code for the high-level quantum function transform that executes compilation.""" -import warnings - # pylint: disable=too-many-branches from functools import partial @@ -35,7 +33,7 @@ @transform def compile( - tape: QuantumScript, pipeline=None, basis_set=None, num_passes=1, expand_depth=None + tape: QuantumScript, pipeline=None, basis_set=None, num_passes=1 ) -> tuple[QuantumScriptBatch, PostprocessingFn]: """Compile a circuit by applying a series of transforms to a quantum function. @@ -48,9 +46,6 @@ def compile( - merging adjacent rotations of the same type (:func:`~pennylane.transforms.merge_rotations`) - .. warning:: - The ``expand_depth`` argument is deprecated and will be removed in version 0.40. - Args: tape (QNode or QuantumTape or Callable): A quantum circuit. pipeline (list[Callable]): A list of @@ -65,7 +60,6 @@ def compile( however, doing so may produce a new circuit where applying the set of transforms again may yield further improvement, so the number of such passes can be adjusted. - expand_depth (int): The depth to use for tape expansion into the basis gates. Returns: qnode (QNode) or quantum function (Callable) or tuple[List[QuantumTape], function]: The compiled circuit. The output type is explained in :func:`qml.transform `. @@ -167,13 +161,6 @@ def qfunc(x, y, z): ───RY(-1.57)─╰X─┤ """ - if expand_depth is not None: - warnings.warn( - "The expand_depth argument is deprecated and will be removed in version v0.40.", - qml.PennyLaneDeprecationWarning, - ) - else: - expand_depth = 5 # Ensure that everything in the pipeline is a valid qfunc or tape transform if pipeline is None: @@ -205,7 +192,6 @@ def stop_at(obj): [expanded_tape], _ = qml.devices.preprocess.decompose( tape, stopping_condition=stop_at, - max_expansion=expand_depth, name="compile", error=qml.operation.DecompositionUndefinedError, skip_initial_state_prep=False, diff --git a/pennylane/transforms/decompositions/clifford_t_transform.py b/pennylane/transforms/decompositions/clifford_t_transform.py index 814bb35158e..8b20c0d1def 100644 --- a/pennylane/transforms/decompositions/clifford_t_transform.py +++ b/pennylane/transforms/decompositions/clifford_t_transform.py @@ -311,7 +311,6 @@ def _merge_param_gates(operations, merge_ops=None): def clifford_t_decomposition( tape: QuantumScript, epsilon=1e-4, - max_expansion=None, method="sk", **method_kwargs, ) -> tuple[QuantumScriptBatch, PostprocessingFn]: @@ -328,13 +327,9 @@ def clifford_t_decomposition( :math:`\epsilon > 0` error. By default, we use the Solovay-Kitaev algorithm described in `Dawson and Nielsen (2005) `_ for this. - .. warning:: - The ``max_expansion`` argument is deprecated and will be removed in version 0.40. - Args: tape (QNode or QuantumTape or Callable): The quantum circuit to be decomposed. epsilon (float): The maximum permissible operator norm error of the complete circuit decomposition. Defaults to ``0.0001``. - max_expansion (int): The depth to be used for tape expansion before manual decomposition to Clifford+T basis is applied. method (str): Method to be used for Clifford+T decomposition. Default value is ``"sk"`` for Solovay-Kitaev. **method_kwargs: Keyword argument to pass options for the ``method`` used for decompositions. @@ -373,13 +368,6 @@ def circuit(x, y): >>> qml.math.allclose(result, approx, atol=1e-4) True """ - if max_expansion is not None: - warnings.warn( - "The max_expansion argument is deprecated and will be removed in version v0.40. ", - qml.PennyLaneDeprecationWarning, - ) - else: - max_expansion = 6 with QueuingManager.stop_recording(): # Build the basis set and the pipeline for intial compilation pass @@ -387,15 +375,7 @@ def circuit(x, y): pipelines = [remove_barrier, commute_controlled, cancel_inverses, merge_rotations] # Compile the tape according to depth provided by the user and expand it - with warnings.catch_warnings(): - warnings.filterwarnings( - action="ignore", - message=r"The expand_depth argument is deprecated", - category=qml.PennyLaneDeprecationWarning, - ) - [compiled_tape], _ = qml.compile( - tape, pipelines, basis_set=basis_set, expand_depth=max_expansion - ) + [compiled_tape], _ = qml.compile(tape, pipelines, basis_set=basis_set) # Now iterate over the expanded tape operations decomp_ops, gphase_ops = [], [] diff --git a/tests/transforms/core/test_transform_dispatcher.py b/tests/transforms/core/test_transform_dispatcher.py index 94b3266ad6a..0ded4a61783 100644 --- a/tests/transforms/core/test_transform_dispatcher.py +++ b/tests/transforms/core/test_transform_dispatcher.py @@ -156,25 +156,18 @@ class TestTransformContainer: def test_repr(self): """Tests for the repr of a transform container.""" t1 = qml.transforms.core.TransformContainer( - qml.transforms.compile.transform, kwargs={"num_passes": 2, "expand_depth": 1} + qml.transforms.compile.transform, kwargs={"num_passes": 2} ) - assert repr(t1) == "" + assert repr(t1) == "" def test_equality(self): """Tests that we can compare TransformContainer objects with the '==' and '!=' operators.""" - t1 = TransformContainer( - qml.transforms.compile.transform, kwargs={"num_passes": 2, "expand_depth": 1} - ) - t2 = TransformContainer( - qml.transforms.compile.transform, kwargs={"num_passes": 2, "expand_depth": 1} - ) + t1 = TransformContainer(qml.transforms.compile.transform, kwargs={"num_passes": 2}) + t2 = TransformContainer(qml.transforms.compile.transform, kwargs={"num_passes": 2}) t3 = TransformContainer( qml.transforms.transpile.transform, kwargs={"coupling_map": [(0, 1), (1, 2)]} ) - t4 = TransformContainer( - qml.transforms.compile.transform, kwargs={"num_passes": 2, "expand_depth": 2} - ) t5 = TransformContainer(qml.transforms.merge_rotations.transform, args=(1e-6,)) t6 = TransformContainer(qml.transforms.merge_rotations.transform, args=(1e-7,)) @@ -186,7 +179,6 @@ def test_equality(self): assert t1 != t3 assert t2 != t3 assert t1 != 2 - assert t1 != t4 assert t5 != t6 assert t5 != t1 diff --git a/tests/transforms/core/test_transform_program.py b/tests/transforms/core/test_transform_program.py index 4e7c6b90ee5..45fa8759a25 100644 --- a/tests/transforms/core/test_transform_program.py +++ b/tests/transforms/core/test_transform_program.py @@ -311,12 +311,8 @@ def test_repr_program(self): def test_equality(self): """Tests that we can compare TransformProgram objects with the '==' and '!=' operators.""" - t1 = TransformContainer( - qml.transforms.compile.transform, kwargs={"num_passes": 2, "expand_depth": 1} - ) - t2 = TransformContainer( - qml.transforms.compile.transform, kwargs={"num_passes": 2, "expand_depth": 1} - ) + t1 = TransformContainer(qml.transforms.compile.transform, kwargs={"num_passes": 2}) + t2 = TransformContainer(qml.transforms.compile.transform, kwargs={"num_passes": 2}) t3 = TransformContainer( qml.transforms.transpile.transform, kwargs={"coupling_map": [(0, 1), (1, 2)]} ) diff --git a/tests/transforms/test_cliffordt_transform.py b/tests/transforms/test_cliffordt_transform.py index e7af710fb1a..5186e1f1269 100644 --- a/tests/transforms/test_cliffordt_transform.py +++ b/tests/transforms/test_cliffordt_transform.py @@ -80,18 +80,6 @@ def circuit_5(): return qml.expval(qml.PauliZ(0)) -def test_max_expansion_is_deprecated(): - """Tests that max_expansion is deprecated""" - with pytest.warns( - qml.PennyLaneDeprecationWarning, - match="The max_expansion argument is deprecated", - ): - tape = qml.tape.QuantumScript([qml.QubitUnitary(qml.math.eye(8), wires=[0, 1, 2])]) - - with pytest.raises(ValueError, match="Cannot unroll"): - clifford_t_decomposition(tape, max_expansion=0) - - class TestCliffordCompile: """Unit tests for clifford compilation function.""" @@ -296,10 +284,7 @@ def test_raise_with_cliffordt_decomposition(self): tape = qml.tape.QuantumScript([qml.QubitUnitary(qml.math.eye(8), wires=[0, 1, 2])]) with pytest.raises(ValueError, match="Cannot unroll"): - with pytest.warns( - qml.PennyLaneDeprecationWarning, match="max_expansion argument is deprecated" - ): - clifford_t_decomposition(tape, max_expansion=0) + clifford_t_decomposition(tape) @pytest.mark.parametrize("op", [qml.U1(1.0, wires=["b"])]) def test_raise_with_rot_decomposition(self, op): diff --git a/tests/transforms/test_compile.py b/tests/transforms/test_compile.py index 6f67c42188c..cb79df6b8b3 100644 --- a/tests/transforms/test_compile.py +++ b/tests/transforms/test_compile.py @@ -33,19 +33,6 @@ from pennylane.wires import Wires -def test_expand_depth_is_deprecated(): - """Tests that expand_depth is deprecated""" - with pytest.warns( - qml.PennyLaneDeprecationWarning, - match="The expand_depth argument is deprecated", - ): - ops = (qml.RX(0.1, 0), qml.RX(0.2, 0), qml.Barrier(only_visual=True), qml.X(0), qml.X(0)) - ms = (qml.expval(qml.X(0)), qml.expval(qml.Y(0))) - tape = qml.tape.QuantumScript(ops, ms, shots=50) - - _, _ = qml.compile(tape, expand_depth=2) - - def build_qfunc(wires): def qfunc(x, y, z): qml.Hadamard(wires=wires[0]) From c3d16430ad7cacb898248f9ed7b321b05d81ee53 Mon Sep 17 00:00:00 2001 From: andrijapau Date: Thu, 7 Nov 2024 11:20:50 -0500 Subject: [PATCH 2/5] forgot lol --- tests/transforms/test_cliffordt_transform.py | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/tests/transforms/test_cliffordt_transform.py b/tests/transforms/test_cliffordt_transform.py index 5186e1f1269..1713f3f03a8 100644 --- a/tests/transforms/test_cliffordt_transform.py +++ b/tests/transforms/test_cliffordt_transform.py @@ -102,20 +102,15 @@ def test_clifford_checker(self, op, res): assert check_clifford_t(op, use_decomposition=True) == res @pytest.mark.parametrize( - ("circuit, max_expansion"), - [(circuit_1, 1), (circuit_2, 0), (circuit_3, 0), (circuit_4, 1), (circuit_5, 0)], + "circuit", + [circuit_1, circuit_2, circuit_3, circuit_4, circuit_5], ) - def test_decomposition(self, circuit, max_expansion): + def test_decomposition(self, circuit): """Test decomposition for the Clifford transform.""" old_tape = qml.tape.make_qscript(circuit)() - with pytest.warns( - qml.PennyLaneDeprecationWarning, match="max_expansion argument is deprecated" - ): - [new_tape], tape_fn = clifford_t_decomposition( - old_tape, max_expansion=max_expansion, max_depth=3 - ) + [new_tape], tape_fn = clifford_t_decomposition(old_tape, max_depth=3) assert all( isinstance(op, _CLIFFORD_PHASE_GATES) From fd49c4cdf0a2658e111e8bb3610186342ef9ad87 Mon Sep 17 00:00:00 2001 From: Andrija Paurevic <46359773+andrijapau@users.noreply.github.com> Date: Fri, 8 Nov 2024 09:24:36 -0500 Subject: [PATCH 3/5] Update doc/releases/changelog-dev.md Co-authored-by: Mudit Pandey --- doc/releases/changelog-dev.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md index 94afe51d561..3ffc947b1d7 100644 --- a/doc/releases/changelog-dev.md +++ b/doc/releases/changelog-dev.md @@ -39,9 +39,11 @@

Breaking changes 💔

-* The ``max_expansion`` argument for :func:`~pennylane.transforms.decompositions.clifford_t_decomposition` has been removed. +* The `max_expansion` argument for `qml.transforms.clifford_t_decomposition` has been removed. + [(#6531)](https://github.com/PennyLaneAI/pennylane/pull/6531) -* The ``expand_depth`` argument for :func:`~pennylane.transforms.compile` has been removed. +* The `expand_depth` argument for `qml.compile` has been removed. + [(#6531)](https://github.com/PennyLaneAI/pennylane/pull/6531)

Deprecations 👋

From 07587f12392482cc089d20891589a666b76ffb82 Mon Sep 17 00:00:00 2001 From: andrijapau Date: Mon, 11 Nov 2024 11:28:11 -0500 Subject: [PATCH 4/5] add test for helper function to fix codecov --- tests/transforms/test_cliffordt_transform.py | 36 ++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/tests/transforms/test_cliffordt_transform.py b/tests/transforms/test_cliffordt_transform.py index 1713f3f03a8..481418b426f 100644 --- a/tests/transforms/test_cliffordt_transform.py +++ b/tests/transforms/test_cliffordt_transform.py @@ -21,6 +21,7 @@ import pennylane as qml from pennylane.transforms.decompositions.clifford_t_transform import ( _CLIFFORD_T_GATES, + _merge_param_gates, _one_qubit_decompose, _rot_decompose, _two_qubit_decompose, @@ -273,6 +274,41 @@ def test_rot_decomposition(self, op): )[qml.math.nonzero(qml.math.round(matrix_op, 10))] assert qml.math.allclose(phase / phase[0], qml.math.ones(qml.math.shape(phase)[0])) + def test_merge_param_gates(self): + """Test _merge_param_gates helper function""" + operations = [ + qml.RX(0.1, wires=0), + qml.RX(0.2, wires=0), + qml.RY(0.3, wires=1), + qml.RY(0.4, wires=1), + qml.RX(0.5, wires=0), + ] + + merge_ops = {"RX", "RY"} + + merged_ops, number_ops = _merge_param_gates(operations, merge_ops=merge_ops) + + assert len(merged_ops) == 2 + assert number_ops == 2 + + assert isinstance(merged_ops[0], qml.RX) + assert merged_ops[0].parameters == [0.8] # 0.1 + 0.2 + 0.5 for wire 0 + assert isinstance(merged_ops[1], qml.RY) + assert merged_ops[1].parameters == [0.7] # 0.3 + 0.4 for wire 1 + + merge_ops.discard("RY") + merged_ops, number_ops = _merge_param_gates(operations, merge_ops=merge_ops) + + assert len(merged_ops) == 3 + assert number_ops == 1 + + assert isinstance(merged_ops[0], qml.RX) + assert merged_ops[0].parameters == [0.8] # 0.1 + 0.2 + 0.5 for wire 0 + assert isinstance(merged_ops[1], qml.RY) + assert merged_ops[1].parameters == [0.3] # 0.3 for wire 1 + assert isinstance(merged_ops[1], qml.RY) + assert merged_ops[2].parameters == [0.4] # 0.4 for wire 1 + def test_raise_with_cliffordt_decomposition(self): """Test that exception is correctly raise when decomposing gates without any decomposition""" From 474bcffbb40153027b868703f0e3e8029cdfe7a3 Mon Sep 17 00:00:00 2001 From: andrijapau Date: Mon, 11 Nov 2024 14:22:13 -0500 Subject: [PATCH 5/5] add test for branch coverage and fix typos --- .../decompositions/clifford_t_transform.py | 4 +- tests/transforms/test_cliffordt_transform.py | 39 ++++++++++++++++++- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/pennylane/transforms/decompositions/clifford_t_transform.py b/pennylane/transforms/decompositions/clifford_t_transform.py index 8b20c0d1def..06e656a0af5 100644 --- a/pennylane/transforms/decompositions/clifford_t_transform.py +++ b/pennylane/transforms/decompositions/clifford_t_transform.py @@ -370,7 +370,7 @@ def circuit(x, y): """ with QueuingManager.stop_recording(): - # Build the basis set and the pipeline for intial compilation pass + # Build the basis set and the pipeline for initial compilation pass basis_set = [op.__name__ for op in _PARAMETER_GATES + _CLIFFORD_T_GATES] pipelines = [remove_barrier, commute_controlled, cancel_inverses, merge_rotations] @@ -433,7 +433,7 @@ def circuit(x, y): # Resort to decomposing manually d_ops = _two_qubit_decompose(md_op) - # Final resort (should not enter in an ideal situtation) + # Final resort (should not enter in an ideal situation) else: d_ops = md_op.decomposition() diff --git a/tests/transforms/test_cliffordt_transform.py b/tests/transforms/test_cliffordt_transform.py index 481418b426f..db3dc9cbca1 100644 --- a/tests/transforms/test_cliffordt_transform.py +++ b/tests/transforms/test_cliffordt_transform.py @@ -81,6 +81,13 @@ def circuit_5(): return qml.expval(qml.PauliZ(0)) +def circuit_6(): + """Circuit 6 with skippable operations""" + qml.RZ(1.0, wires=[0]) + qml.Barrier(wires=0) + return qml.expval(qml.PauliZ(0)) + + class TestCliffordCompile: """Unit tests for clifford compilation function.""" @@ -104,7 +111,7 @@ def test_clifford_checker(self, op, res): @pytest.mark.parametrize( "circuit", - [circuit_1, circuit_2, circuit_3, circuit_4, circuit_5], + [circuit_1, circuit_2, circuit_3, circuit_4, circuit_5, circuit_6], ) def test_decomposition(self, circuit): """Test decomposition for the Clifford transform.""" @@ -172,6 +179,36 @@ def test_total_error(self, epsilon, circuit): error = qml.math.sqrt(qml.math.real(qml.math.trace(qml.math.conj(diff).T @ diff)) / 2) assert error < epsilon + @pytest.mark.parametrize( + "op", + [ + qml.RY(qml.numpy.pi / 4, wires=0), + ], + ) + def test_zxz_rotation_decomposition(self, op): + """Test single-qubit gates are decomposed correctly using ZXZ rotations""" + + def circuit(): + qml.apply(op) + return qml.probs(wires=0) + + old_tape = qml.tape.make_qscript(circuit)() + + [new_tape], tape_fn = clifford_t_decomposition(old_tape, max_depth=3) + + assert all( + isinstance(op, _CLIFFORD_PHASE_GATES) + or isinstance(getattr(op, "base", None), _CLIFFORD_PHASE_GATES) + for op in new_tape.operations + ) + + dev = qml.device("default.qubit") + transform_program, _ = dev.preprocess() + res1, res2 = qml.execute( + [old_tape, new_tape], device=dev, transform_program=transform_program + ) + qml.math.isclose(res1, tape_fn([res2]), atol=1e-2) + @pytest.mark.parametrize( "op", [qml.RX(1.0, wires="a"), qml.U3(1, 2, 3, wires=[1]), qml.PhaseShift(1.0, wires=[2])] )