From bbcb77ba5fea42cb5f999c0c8b2d33871053bfae Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Mon, 15 Dec 2025 20:07:26 -0500 Subject: [PATCH 1/3] Replace `TransformProgram` with `CompilePipeline` --- frontend/catalyst/device/qjit_device.py | 8 ++++---- frontend/catalyst/jax_tracer.py | 6 +++--- frontend/catalyst/qfunc.py | 4 ++-- frontend/catalyst/third_party/oqc/oqc_device.py | 4 ++-- frontend/catalyst/third_party/oqd/oqd_device.py | 4 ++-- frontend/test/lit/test_device_api.py | 4 ++-- frontend/test/pytest/test_measurement_transforms.py | 2 +- .../test/pytest/test_measurements_shots_results.py | 12 ++++++------ frontend/test/test_oqc/oqc/test_oqc_device.py | 4 ++-- frontend/test/test_oqd/oqd/test_oqd_device.py | 4 ++-- 10 files changed, 26 insertions(+), 26 deletions(-) diff --git a/frontend/catalyst/device/qjit_device.py b/frontend/catalyst/device/qjit_device.py index 77aa57e5aa..fe2de6eecd 100644 --- a/frontend/catalyst/device/qjit_device.py +++ b/frontend/catalyst/device/qjit_device.py @@ -38,7 +38,7 @@ split_non_commuting, split_to_single_terms, ) -from pennylane.transforms.core import TransformProgram +from pennylane.transforms.core import CompilePipeline from catalyst.device.decomposition import ( catalyst_decompose, @@ -360,7 +360,7 @@ def preprocess( describing parameters of the execution. Returns: - TransformProgram: A transform program that when called returns QuantumTapes that can be + CompilePipeline: A transform program that when called returns QuantumTapes that can be compiled for the backend, and a postprocessing function to be called on the results ExecutionConfig: configuration with unset specifications filled in if relevant. @@ -373,7 +373,7 @@ def preprocess( execution_config = qml.devices.ExecutionConfig() _, config = self.original_device.preprocess(execution_config) - program = TransformProgram() + program = CompilePipeline() # During preprocessing, we now have info on whether the user is requesting execution # with shots. @@ -432,7 +432,7 @@ def preprocess( return program, config def _measurement_transform_program(self, capabilities): - measurement_program = TransformProgram() + measurement_program = CompilePipeline() if isinstance(self.original_device, SoftwareQQPP): return measurement_program diff --git a/frontend/catalyst/jax_tracer.py b/frontend/catalyst/jax_tracer.py index e73597298c..3bb956d254 100644 --- a/frontend/catalyst/jax_tracer.py +++ b/frontend/catalyst/jax_tracer.py @@ -49,7 +49,7 @@ from pennylane.operation import Operation, Operator, Wires from pennylane.ops import Adjoint, Controlled, ControlledOp from pennylane.tape import QuantumTape -from pennylane.transforms.core import TransformProgram +from pennylane.transforms.core import CompilePipeline import catalyst from catalyst.api_extensions.callbacks import MemrefCallable @@ -1526,9 +1526,9 @@ def is_leaf(obj): config = _make_execution_config(qnode) device_program, config = device.preprocess(ctx, execution_config=config, shots=shots) else: - device_program = TransformProgram() + device_program = CompilePipeline() - qnode_program = qnode.transform_program if qnode else TransformProgram() + qnode_program = qnode.transform_program if qnode else CompilePipeline() tapes, post_processing, tracing_mode = apply_transforms( qnode_program, diff --git a/frontend/catalyst/qfunc.py b/frontend/catalyst/qfunc.py index b0af042dbe..f46a22e2ad 100644 --- a/frontend/catalyst/qfunc.py +++ b/frontend/catalyst/qfunc.py @@ -663,7 +663,7 @@ def wrap_single_shot_qnode(*_): def _extract_passes(transform_program): - """Extract transforms with pass names from the end of the TransformProgram.""" + """Extract transforms with pass names from the end of the CompilePipeline.""" tape_transforms = [] pass_pipeline = [] i = len(transform_program) @@ -678,4 +678,4 @@ def _extract_passes(transform_program): raise ValueError( f"{t} without a tape definition occurs before tape transform {tape_transforms[-1]}." ) - return qml.transforms.core.TransformProgram(tape_transforms), tuple(pass_pipeline) + return qml.transforms.core.CompilePipeline(tape_transforms), tuple(pass_pipeline) diff --git a/frontend/catalyst/third_party/oqc/oqc_device.py b/frontend/catalyst/third_party/oqc/oqc_device.py index 8d2f794881..0d090e5c1f 100644 --- a/frontend/catalyst/third_party/oqc/oqc_device.py +++ b/frontend/catalyst/third_party/oqc/oqc_device.py @@ -19,7 +19,7 @@ from typing import Optional from pennylane.devices import Device, ExecutionConfig -from pennylane.transforms.core import TransformProgram +from pennylane.transforms.core import CompilePipeline try: from qcaas_client.client import OQCClient # pylint: disable=unused-import @@ -69,7 +69,7 @@ def preprocess( if execution_config is None: execution_config = ExecutionConfig() - transform_program = TransformProgram() + transform_program = CompilePipeline() # TODO: Add transforms (check wires, check shots, no sample, only commuting measurements, # measurement from counts) return transform_program, execution_config diff --git a/frontend/catalyst/third_party/oqd/oqd_device.py b/frontend/catalyst/third_party/oqd/oqd_device.py index dc725afae8..6b7536bd6f 100644 --- a/frontend/catalyst/third_party/oqd/oqd_device.py +++ b/frontend/catalyst/third_party/oqd/oqd_device.py @@ -23,7 +23,7 @@ import platform from pennylane.devices import Device, ExecutionConfig -from pennylane.transforms.core import TransformProgram +from pennylane.transforms.core import CompilePipeline from catalyst.compiler import get_lib_path BACKENDS = ["default"] @@ -130,7 +130,7 @@ def preprocess( if execution_config is None: execution_config = ExecutionConfig() - transform_program = TransformProgram() + transform_program = CompilePipeline() return transform_program, execution_config diff --git a/frontend/test/lit/test_device_api.py b/frontend/test/lit/test_device_api.py index 55a3096064..132eaa897f 100644 --- a/frontend/test/lit/test_device_api.py +++ b/frontend/test/lit/test_device_api.py @@ -25,7 +25,7 @@ import pennylane as qml from pennylane.devices import Device from pennylane.devices.execution_config import ExecutionConfig -from pennylane.transforms.core import TransformProgram +from pennylane.transforms.core import CompilePipeline from catalyst import qjit from catalyst.compiler import get_lib_path @@ -63,7 +63,7 @@ def preprocess(self, execution_config: Optional[ExecutionConfig] = None): if execution_config is None: execution_config = ExecutionConfig() - transform_program = TransformProgram() + transform_program = CompilePipeline() transform_program.add_transform(qml.transforms.split_non_commuting) return transform_program, execution_config diff --git a/frontend/test/pytest/test_measurement_transforms.py b/frontend/test/pytest/test_measurement_transforms.py index e2aae968e6..51d71181a6 100644 --- a/frontend/test/pytest/test_measurement_transforms.py +++ b/frontend/test/pytest/test_measurement_transforms.py @@ -628,7 +628,7 @@ def circuit(theta: float): ], ) def test_diagonalize_measurements_added_to_transforms(self, unsupported_obs, mocker): - """Test that the diagonalize_measurements transform is included in the TransformProgram + """Test that the diagonalize_measurements transform is included in the CompilePipeline as expected when we are not diagonalizing everything to counts or samples, but some of {X, Y, Z, H} are not supported.""" diff --git a/frontend/test/pytest/test_measurements_shots_results.py b/frontend/test/pytest/test_measurements_shots_results.py index 08caeb47b2..57a22dde3b 100644 --- a/frontend/test/pytest/test_measurements_shots_results.py +++ b/frontend/test/pytest/test_measurements_shots_results.py @@ -643,7 +643,7 @@ def all_measurements(x): ) @qml.set_shots(shots=10000) - @qml.qnode(qml.device("lightning.qubit", wires=2)) + @qml.qnode(qml.device("lightning.qubit", wires=2), static_argnums=(1,)) def expected(x, measurement_fn): qml.RY(x, wires=0) return measurement_fn() @@ -652,13 +652,13 @@ def expected(x, measurement_fn): result = all_measurements(x) # qml.sample - assert result[0].shape == expected(x, measurement_fn=lambda: qml.sample(wires=[0, 1])).shape + assert result[0].shape == expected(x, lambda: qml.sample(wires=[0, 1])).shape assert result[0].dtype == np.int64 # qml.counts qml.capture.disable() # cant execute with counts with program capture for r, e in zip( - result[1][0], expected(x, measurement_fn=lambda: qml.counts(all_outcomes=True)) + result[1][0], expected(x, lambda: qml.counts(all_outcomes=True)) ): assert format(int(r), "02b") == e assert sum(result[1][1]) == 10000 @@ -667,7 +667,7 @@ def expected(x, measurement_fn): # qml.expval assert np.allclose( result[2], - expected(x, measurement_fn=lambda: qml.expval(qml.PauliZ(0))), + expected(x, lambda: qml.expval(qml.PauliZ(0))), atol=tol_stochastic, rtol=tol_stochastic, ) @@ -675,7 +675,7 @@ def expected(x, measurement_fn): # qml.var assert np.allclose( result[3], - expected(x, measurement_fn=lambda: qml.var(qml.PauliZ(0))), + expected(x, lambda: qml.var(qml.PauliZ(0))), atol=tol_stochastic, rtol=tol_stochastic, ) @@ -683,7 +683,7 @@ def expected(x, measurement_fn): # qml.probs assert np.allclose( result[4], - expected(x, measurement_fn=lambda: qml.probs(wires=[0, 1])), + expected(x, lambda: qml.probs(wires=[0, 1])), atol=tol_stochastic, rtol=tol_stochastic, ) diff --git a/frontend/test/test_oqc/oqc/test_oqc_device.py b/frontend/test/test_oqc/oqc/test_oqc_device.py index d1113042b2..7a9d2f27ad 100644 --- a/frontend/test/test_oqc/oqc/test_oqc_device.py +++ b/frontend/test/test_oqc/oqc/test_oqc_device.py @@ -71,7 +71,7 @@ def test_preprocess(self, set_dummy_oqc_env): dev = OQCDevice(backend="lucy", shots=1000, wires=8) tranform_program, _ = dev.preprocess() - assert tranform_program == qml.transforms.core.TransformProgram() + assert tranform_program == qml.transforms.core.CompilePipeline() def test_preprocess_with_config(self, set_dummy_oqc_env): """Test the device preprocessing by explicitly passing an execution config""" @@ -80,7 +80,7 @@ def test_preprocess_with_config(self, set_dummy_oqc_env): dev = OQCDevice(backend="lucy", shots=1000, wires=8) execution_config = qml.devices.ExecutionConfig() tranform_program, config = dev.preprocess(execution_config) - assert tranform_program == qml.transforms.core.TransformProgram() + assert tranform_program == qml.transforms.core.CompilePipeline() assert config == execution_config def test_get_c_interface(self, set_dummy_oqc_env): diff --git a/frontend/test/test_oqd/oqd/test_oqd_device.py b/frontend/test/test_oqd/oqd/test_oqd_device.py index 65b22626d3..8ecd9d655e 100644 --- a/frontend/test/test_oqd/oqd/test_oqd_device.py +++ b/frontend/test/test_oqd/oqd/test_oqd_device.py @@ -49,14 +49,14 @@ def test_preprocess(self): """Test the device preprocessing""" dev = OQDDevice(backend="default", wires=8) tranform_program, _ = dev.preprocess() - assert tranform_program == qml.transforms.core.TransformProgram() + assert tranform_program == qml.transforms.core.CompilePipeline() def test_preprocess_with_config(self): """Test the device preprocessing by explicitly passing an execution config""" dev = OQDDevice(backend="default", wires=8) execution_config = qml.devices.ExecutionConfig() tranform_program, config = dev.preprocess(execution_config) - assert tranform_program == qml.transforms.core.TransformProgram() + assert tranform_program == qml.transforms.core.CompilePipeline() assert config == execution_config def test_get_c_interface(self): From 34e1bab3cf6c3ebaf05ebf4f0b1ae95456b173cf Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Mon, 15 Dec 2025 20:09:04 -0500 Subject: [PATCH 2/3] bump dep version --- .dep-versions | 2 +- doc/requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.dep-versions b/.dep-versions index f7e68582d9..cd0f7ba003 100644 --- a/.dep-versions +++ b/.dep-versions @@ -10,7 +10,7 @@ enzyme=v0.0.203 # For a custom PL version, update the package version here and at # 'doc/requirements.txt' -pennylane=0.44.0-dev50 +pennylane=0.44.0-dev52 # For a custom LQ/LK version, update the package version here and at # 'doc/requirements.txt' diff --git a/doc/requirements.txt b/doc/requirements.txt index 503092fb69..5d88cf6c5e 100644 --- a/doc/requirements.txt +++ b/doc/requirements.txt @@ -33,4 +33,4 @@ lxml_html_clean --extra-index-url https://test.pypi.org/simple/ pennylane-lightning-kokkos==0.44.0-dev16 pennylane-lightning==0.44.0-dev16 -pennylane==0.44.0-dev50 +pennylane==0.44.0-dev52 From 6f21f486f3c91f34e49f56be67afd1f97ce30771 Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Mon, 15 Dec 2025 20:11:40 -0500 Subject: [PATCH 3/3] format --- frontend/test/pytest/test_measurements_shots_results.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/frontend/test/pytest/test_measurements_shots_results.py b/frontend/test/pytest/test_measurements_shots_results.py index 57a22dde3b..4925ebcad7 100644 --- a/frontend/test/pytest/test_measurements_shots_results.py +++ b/frontend/test/pytest/test_measurements_shots_results.py @@ -657,9 +657,7 @@ def expected(x, measurement_fn): # qml.counts qml.capture.disable() # cant execute with counts with program capture - for r, e in zip( - result[1][0], expected(x, lambda: qml.counts(all_outcomes=True)) - ): + for r, e in zip(result[1][0], expected(x, lambda: qml.counts(all_outcomes=True))): assert format(int(r), "02b") == e assert sum(result[1][1]) == 10000 assert result[1][0].dtype == np.int64