From 0b092becd0705a2c17b8b950c23199f6b5c60f8d Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Wed, 30 Apr 2025 11:26:22 -0400 Subject: [PATCH 01/42] Make the pipeline compatible with shots decoupling From 4696be86984a9b12881e57074907d55bbe2b8abb Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Wed, 30 Apr 2025 15:42:12 -0400 Subject: [PATCH 02/42] changelog --- doc/releases/changelog-dev.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md index 7bd1046cde2..5e5fb8f1e99 100644 --- a/doc/releases/changelog-dev.md +++ b/doc/releases/changelog-dev.md @@ -7,6 +7,7 @@ * A new transfomer :func:`~.transforms.set_shots` has been added to set the number of shots for all QNodes in a pipeline. This transform can be used to set the number of shots for all QNodes in a pipeline. [(#7337)](https://github.com/PennyLaneAI/pennylane/pull/7337) + [(#7358)](https://github.com/PennyLaneAI/pennylane/pull/7358) * A new template called :class:`~.SelectPauliRot` that applies a sequence of uniformly controlled rotations to a target qubit is now available. This operator appears frequently in unitary decomposition and block encoding techniques. @@ -210,6 +211,9 @@

Internal changes ⚙️

+* Ajusted execution pipeline to be compatible with the new `set_shots` transform. + [(#7358)](https://github.com/PennyLaneAI/pennylane/pull/7358) + * A new internal module, `qml.concurrency`, is added to support internal use of multiprocess and multithreaded execution of workloads. This also migrates the use of `concurrent.futures` in `default.qubit` to this new design. [(#7303)](https://github.com/PennyLaneAI/pennylane/pull/7303) From c72484b104e39e7c57ac0a355518bb32faa7b38c Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Wed, 30 Apr 2025 16:30:15 -0400 Subject: [PATCH 03/42] add top level test --- tests/transforms/test_set_shots.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/transforms/test_set_shots.py b/tests/transforms/test_set_shots.py index 4882698cfae..e143028f076 100644 --- a/tests/transforms/test_set_shots.py +++ b/tests/transforms/test_set_shots.py @@ -96,3 +96,8 @@ def circuit(x): # !Note: this should be fixed after the pipeline is updated to use the new set_shots transform with pytest.raises(qml.DeviceError, match="Finite shots are not supported with backprop"): circuit(x) + + @pytest.mark.integration + def test_toplevel_accessible(self): + """Test that qml.set_shots is available at top-level.""" + assert hasattr(qml, "set_shots") From ce09b002739fd4f67eaca3c7e443856b3013d095 Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Wed, 30 Apr 2025 17:02:40 -0400 Subject: [PATCH 04/42] an ugly, initial approach --- pennylane/workflow/execution.py | 8 ++++++++ tests/transforms/test_set_shots.py | 6 ++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/pennylane/workflow/execution.py b/pennylane/workflow/execution.py index d39ff6a6d1e..2ec16cefd34 100644 --- a/pennylane/workflow/execution.py +++ b/pennylane/workflow/execution.py @@ -160,6 +160,14 @@ def cost_fn(params, x): if not isinstance(device, qml.devices.Device): device = qml.devices.LegacyDeviceFacade(device) + # If the transform program contains set_shots, we need to adjust the tape + if transform_program is not None and any( + getattr(getattr(t, "_transform"), "__name__", "") == "set_shots" + for t in getattr(transform_program, "_transform_program", []) + ): + tapes, _ = transform_program(tapes) + transform_program = None + if logger.isEnabledFor(logging.DEBUG): logger.debug( ( diff --git a/tests/transforms/test_set_shots.py b/tests/transforms/test_set_shots.py index e143028f076..f6cf3725f40 100644 --- a/tests/transforms/test_set_shots.py +++ b/tests/transforms/test_set_shots.py @@ -84,7 +84,7 @@ def test_error_finite_shots_with_backprop(self): """Test that DeviceError is raised if finite shots are used with backprop + default.qubit.""" dev = qml.device("default.qubit", wires=2) - @partial(set_shots, shots=1000) + @partial(set_shots, shots=10) @qml.qnode(dev) def circuit(x): qml.RX(x, wires=0) @@ -93,9 +93,7 @@ def circuit(x): return qml.expval(qml.PauliZ(0)), qml.expval(qml.PauliZ(1)) x = qml.numpy.array(0.5) - # !Note: this should be fixed after the pipeline is updated to use the new set_shots transform - with pytest.raises(qml.DeviceError, match="Finite shots are not supported with backprop"): - circuit(x) + assert len(circuit(x)) == 2 @pytest.mark.integration def test_toplevel_accessible(self): From c327519a758795b83d418eddeaa9533415112d1e Mon Sep 17 00:00:00 2001 From: "Yushao Chen (Jerry)" Date: Fri, 2 May 2025 10:15:28 -0400 Subject: [PATCH 05/42] Update pennylane/workflow/execution.py Co-authored-by: Christina Lee --- pennylane/workflow/execution.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/pennylane/workflow/execution.py b/pennylane/workflow/execution.py index 2ec16cefd34..eb2897fe6de 100644 --- a/pennylane/workflow/execution.py +++ b/pennylane/workflow/execution.py @@ -161,13 +161,9 @@ def cost_fn(params, x): device = qml.devices.LegacyDeviceFacade(device) # If the transform program contains set_shots, we need to adjust the tape - if transform_program is not None and any( - getattr(getattr(t, "_transform"), "__name__", "") == "set_shots" - for t in getattr(transform_program, "_transform_program", []) - ): - tapes, _ = transform_program(tapes) - transform_program = None - + if transform_program: + tapes, user_postprocessing = transform_program(tapes) + transform_program = TransformProgram() if logger.isEnabledFor(logging.DEBUG): logger.debug( ( From 794bfa3b8942be3f69d109f579a7fb2b722cf04c Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Fri, 2 May 2025 10:23:05 -0400 Subject: [PATCH 06/42] all interfaze the integration test --- tests/transforms/test_set_shots.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/transforms/test_set_shots.py b/tests/transforms/test_set_shots.py index f6cf3725f40..2672d7324c9 100644 --- a/tests/transforms/test_set_shots.py +++ b/tests/transforms/test_set_shots.py @@ -80,12 +80,14 @@ def test_returns_tuple(self): assert callable(result[1]) @pytest.mark.integration - def test_error_finite_shots_with_backprop(self): + @pytest.mark.all_interfaces + @pytest.mark.parametrize("interface", qml.math.SUPPORTED_INTERFACE_NAMES) + def test_error_finite_shots_with_backprop(self, interface): """Test that DeviceError is raised if finite shots are used with backprop + default.qubit.""" dev = qml.device("default.qubit", wires=2) @partial(set_shots, shots=10) - @qml.qnode(dev) + @qml.qnode(dev, interface=interface) def circuit(x): qml.RX(x, wires=0) qml.RY(x, wires=1) From 1cc24efc054689baa432ea204ad9ff0e27766cf0 Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Fri, 2 May 2025 13:30:11 -0400 Subject: [PATCH 07/42] more tests --- tests/transforms/test_set_shots.py | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/tests/transforms/test_set_shots.py b/tests/transforms/test_set_shots.py index 2672d7324c9..6c0dfd8b81f 100644 --- a/tests/transforms/test_set_shots.py +++ b/tests/transforms/test_set_shots.py @@ -81,12 +81,13 @@ def test_returns_tuple(self): @pytest.mark.integration @pytest.mark.all_interfaces + @pytest.mark.parametrize("shots", [None, 1, 10]) @pytest.mark.parametrize("interface", qml.math.SUPPORTED_INTERFACE_NAMES) - def test_error_finite_shots_with_backprop(self, interface): - """Test that DeviceError is raised if finite shots are used with backprop + default.qubit.""" + def test_compatibility_finite_shots(self, interface, shots): + """Test that setting shots works with default.qubit with default setting up""" dev = qml.device("default.qubit", wires=2) - @partial(set_shots, shots=10) + @partial(set_shots, shots=shots) @qml.qnode(dev, interface=interface) def circuit(x): qml.RX(x, wires=0) @@ -97,6 +98,25 @@ def circuit(x): x = qml.numpy.array(0.5) assert len(circuit(x)) == 2 + @pytest.mark.integration + @pytest.mark.all_interfaces + @pytest.mark.parametrize("shots", [(10, 10, 10), ((10, 3),)]) + @pytest.mark.parametrize("interface", qml.math.SUPPORTED_INTERFACE_NAMES) + def test_shot_vector(self, interface, shots): + """Test that setting shots with shot vectors works with default setting up.""" + dev = qml.device("default.qubit", wires=2) + + @partial(set_shots, shots=shots) + @qml.qnode(dev, interface=interface) + def circuit(x): + qml.RX(x, wires=0) + qml.RY(x, wires=1) + qml.CNOT(wires=[0, 1]) + return qml.expval(qml.PauliZ(0)), qml.expval(qml.PauliZ(1)) + + x = qml.numpy.array(0.5) + assert len(circuit(x)) == 3 + @pytest.mark.integration def test_toplevel_accessible(self): """Test that qml.set_shots is available at top-level.""" From 10181b962495264b01312d623939d8d0e5fac289 Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Fri, 2 May 2025 15:00:38 -0400 Subject: [PATCH 08/42] make outer program named as the context implies --- pennylane/workflow/_setup_transform_program.py | 10 +++++----- pennylane/workflow/execution.py | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pennylane/workflow/_setup_transform_program.py b/pennylane/workflow/_setup_transform_program.py index d0d7c2a65d6..cebe728a787 100644 --- a/pennylane/workflow/_setup_transform_program.py +++ b/pennylane/workflow/_setup_transform_program.py @@ -85,24 +85,24 @@ def _setup_transform_program( device_transform_program = device.preprocess_transforms(resolved_execution_config) - full_transform_program = qml.transforms.core.TransformProgram( + outer_transform_program = qml.transforms.core.TransformProgram( user_transform_program, cotransform_cache=user_transform_program.cotransform_cache ) inner_transform_program = qml.transforms.core.TransformProgram() # Add the gradient expand to the program if necessary if getattr(resolved_execution_config.gradient_method, "expand_transform", False): - full_transform_program.add_transform( + outer_transform_program.add_transform( qml.transform(resolved_execution_config.gradient_method.expand_transform), **resolved_execution_config.gradient_keyword_arguments, ) if resolved_execution_config.use_device_gradient: - full_transform_program += device_transform_program + outer_transform_program += device_transform_program else: inner_transform_program += device_transform_program # Making sure dynamic_one_shot occurs at most once between the inner and outer transform programs - _prune_dynamic_transform(full_transform_program, inner_transform_program) + _prune_dynamic_transform(outer_transform_program, inner_transform_program) # If caching is desired but an explicit cache is not provided, use an ``LRUCache``. if cache is True: @@ -124,4 +124,4 @@ def _setup_transform_program( if cache is not None: inner_transform_program.add_transform(_cache_transform, cache=cache) - return full_transform_program, inner_transform_program + return outer_transform_program, inner_transform_program diff --git a/pennylane/workflow/execution.py b/pennylane/workflow/execution.py index eb2897fe6de..f99fcd7b998 100644 --- a/pennylane/workflow/execution.py +++ b/pennylane/workflow/execution.py @@ -207,14 +207,14 @@ def cost_fn(params, x): config = _resolve_execution_config(config, device, tapes, transform_program=transform_program) transform_program = transform_program or qml.transforms.core.TransformProgram() - transform_program, inner_transform = _setup_transform_program( + outer_transform, inner_transform = _setup_transform_program( transform_program, device, config, cache, cachesize ) #### Executing the configured setup ##### - tapes, post_processing = transform_program(tapes) + tapes, post_processing = outer_transform(tapes) - if transform_program.is_informative: + if outer_transform.is_informative: return post_processing(tapes) results = run(tapes, device, config, inner_transform) From 0597d8c9cc6d215a8ce04b3348ae02fdd238711e Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Fri, 2 May 2025 15:11:27 -0400 Subject: [PATCH 09/42] unused yet. udnerscore for now. --- pennylane/workflow/execution.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane/workflow/execution.py b/pennylane/workflow/execution.py index f99fcd7b998..a7309dbb35d 100644 --- a/pennylane/workflow/execution.py +++ b/pennylane/workflow/execution.py @@ -162,7 +162,7 @@ def cost_fn(params, x): # If the transform program contains set_shots, we need to adjust the tape if transform_program: - tapes, user_postprocessing = transform_program(tapes) + tapes, _ = transform_program(tapes) transform_program = TransformProgram() if logger.isEnabledFor(logging.DEBUG): logger.debug( From fd03178e7536cafe4d8b33497a4018bd836d73c4 Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Fri, 2 May 2025 15:35:41 -0400 Subject: [PATCH 10/42] readability adjust --- pennylane/workflow/execution.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pennylane/workflow/execution.py b/pennylane/workflow/execution.py index a7309dbb35d..ba373544a21 100644 --- a/pennylane/workflow/execution.py +++ b/pennylane/workflow/execution.py @@ -160,10 +160,11 @@ def cost_fn(params, x): if not isinstance(device, qml.devices.Device): device = qml.devices.LegacyDeviceFacade(device) - # If the transform program contains set_shots, we need to adjust the tape + ### Apply the user transforms #### if transform_program: tapes, _ = transform_program(tapes) transform_program = TransformProgram() + if logger.isEnabledFor(logging.DEBUG): logger.debug( ( @@ -191,7 +192,6 @@ def cost_fn(params, x): return () ### Specifying and preprocessing variables #### - interface = _resolve_interface(interface, tapes) config = qml.devices.ExecutionConfig( From 7411a01b098a11e83de5ded00a1814b485c13431 Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Fri, 2 May 2025 15:58:04 -0400 Subject: [PATCH 11/42] [skip-ci] no more xfail --- tests/transforms/test_set_shots.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/transforms/test_set_shots.py b/tests/transforms/test_set_shots.py index 87dc2d072d4..532cf17fbc7 100644 --- a/tests/transforms/test_set_shots.py +++ b/tests/transforms/test_set_shots.py @@ -80,9 +80,6 @@ def test_returns_tuple(self): assert isinstance(result[0], (list, tuple)) assert callable(result[1]) - @pytest.mark.xfail( - reason="This test is expected to fail until the pipeline is updated to use the new set_shots transform" - ) @pytest.mark.integration @pytest.mark.all_interfaces @pytest.mark.parametrize("shots", [None, 1, 10]) From 976734b177c1bcd0d2f43550f928fb4cffc5d2ba Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Mon, 5 May 2025 10:03:15 -0400 Subject: [PATCH 12/42] is_user_transform --- pennylane/transforms/set_shots.py | 3 +++ pennylane/workflow/execution.py | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/pennylane/transforms/set_shots.py b/pennylane/transforms/set_shots.py index 4c80ce135f1..0363578bb30 100644 --- a/pennylane/transforms/set_shots.py +++ b/pennylane/transforms/set_shots.py @@ -57,3 +57,6 @@ def set_shots( if tape.shots != Shots(shots): tape = tape.copy(shots=shots) return (tape,), null_postprocessing + + +set_shots.is_user_transform = True diff --git a/pennylane/workflow/execution.py b/pennylane/workflow/execution.py index ba373544a21..ea7d0626b03 100644 --- a/pennylane/workflow/execution.py +++ b/pennylane/workflow/execution.py @@ -161,7 +161,7 @@ def cost_fn(params, x): device = qml.devices.LegacyDeviceFacade(device) ### Apply the user transforms #### - if transform_program: + if transform_program and getattr(transform_program, "is_user_transform", False): tapes, _ = transform_program(tapes) transform_program = TransformProgram() From c7bacf61de6cc1b20dbecef5449938f1f683731c Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Mon, 5 May 2025 11:15:15 -0400 Subject: [PATCH 13/42] logger needs to record what's passed to execute --- pennylane/workflow/execution.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pennylane/workflow/execution.py b/pennylane/workflow/execution.py index ea7d0626b03..6b5595e7e9d 100644 --- a/pennylane/workflow/execution.py +++ b/pennylane/workflow/execution.py @@ -160,11 +160,6 @@ def cost_fn(params, x): if not isinstance(device, qml.devices.Device): device = qml.devices.LegacyDeviceFacade(device) - ### Apply the user transforms #### - if transform_program and getattr(transform_program, "is_user_transform", False): - tapes, _ = transform_program(tapes) - transform_program = TransformProgram() - if logger.isEnabledFor(logging.DEBUG): logger.debug( ( @@ -188,6 +183,11 @@ def cost_fn(params, x): "::L".join(str(i) for i in inspect.getouterframes(inspect.currentframe(), 2)[1][1:3]), ) + ### Apply the user transforms #### + if transform_program and getattr(transform_program, "is_user_transform", False): + tapes, _ = transform_program(tapes) + transform_program = TransformProgram() + if not tapes: return () From 62942192b8b139db0defec44401bf8a8412a5c48 Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Mon, 5 May 2025 11:21:51 -0400 Subject: [PATCH 14/42] revert and fix: early return if infromatvie --- pennylane/workflow/execution.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pennylane/workflow/execution.py b/pennylane/workflow/execution.py index 6b5595e7e9d..86ba3b75404 100644 --- a/pennylane/workflow/execution.py +++ b/pennylane/workflow/execution.py @@ -184,8 +184,10 @@ def cost_fn(params, x): ) ### Apply the user transforms #### - if transform_program and getattr(transform_program, "is_user_transform", False): - tapes, _ = transform_program(tapes) + if transform_program: + tapes, post_processing = transform_program(tapes) + if transform_program.is_informative: + return post_processing(tapes) transform_program = TransformProgram() if not tapes: From b62f110c53c2475a86ec9741352938166624cd78 Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Mon, 5 May 2025 12:44:22 -0400 Subject: [PATCH 15/42] nameing for user and outer processing; fix the issue that user_processing was forgotten. --- pennylane/workflow/execution.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pennylane/workflow/execution.py b/pennylane/workflow/execution.py index 86ba3b75404..4eb54c2fdf1 100644 --- a/pennylane/workflow/execution.py +++ b/pennylane/workflow/execution.py @@ -185,9 +185,9 @@ def cost_fn(params, x): ### Apply the user transforms #### if transform_program: - tapes, post_processing = transform_program(tapes) + tapes, user_post_processing = transform_program(tapes) if transform_program.is_informative: - return post_processing(tapes) + return user_post_processing(tapes) transform_program = TransformProgram() if not tapes: @@ -214,10 +214,10 @@ def cost_fn(params, x): ) #### Executing the configured setup ##### - tapes, post_processing = outer_transform(tapes) + tapes, outer_post_processing = outer_transform(tapes) if outer_transform.is_informative: - return post_processing(tapes) + return user_post_processing(outer_post_processing(tapes)) results = run(tapes, device, config, inner_transform) - return post_processing(results) + return user_post_processing(outer_post_processing(results)) From 18e401a9f52ccae4bca0555c7d2613dc2c9be71f Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Mon, 5 May 2025 12:49:50 -0400 Subject: [PATCH 16/42] fix --- pennylane/workflow/execution.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pennylane/workflow/execution.py b/pennylane/workflow/execution.py index 4eb54c2fdf1..fac87e0fdfc 100644 --- a/pennylane/workflow/execution.py +++ b/pennylane/workflow/execution.py @@ -184,6 +184,7 @@ def cost_fn(params, x): ) ### Apply the user transforms #### + user_post_processing = lambda x: x # null basically if transform_program: tapes, user_post_processing = transform_program(tapes) if transform_program.is_informative: From 1189998d5611c4cfcc9409196efff6754cd304a5 Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Mon, 5 May 2025 14:56:44 -0400 Subject: [PATCH 17/42] fix: no tape exit should be in the very beginning --- pennylane/workflow/execution.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pennylane/workflow/execution.py b/pennylane/workflow/execution.py index fac87e0fdfc..f77f15e19ef 100644 --- a/pennylane/workflow/execution.py +++ b/pennylane/workflow/execution.py @@ -183,6 +183,9 @@ def cost_fn(params, x): "::L".join(str(i) for i in inspect.getouterframes(inspect.currentframe(), 2)[1][1:3]), ) + if not tapes: + return () + ### Apply the user transforms #### user_post_processing = lambda x: x # null basically if transform_program: @@ -191,9 +194,6 @@ def cost_fn(params, x): return user_post_processing(tapes) transform_program = TransformProgram() - if not tapes: - return () - ### Specifying and preprocessing variables #### interface = _resolve_interface(interface, tapes) From 7b37902374a64be9d2a40615e57907eb6a807584 Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Mon, 5 May 2025 14:57:30 -0400 Subject: [PATCH 18/42] adjust regex match pattern --- tests/gradients/core/test_metric_tensor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/gradients/core/test_metric_tensor.py b/tests/gradients/core/test_metric_tensor.py index e585a43483d..c3b352f8c1a 100644 --- a/tests/gradients/core/test_metric_tensor.py +++ b/tests/gradients/core/test_metric_tensor.py @@ -1560,7 +1560,7 @@ def circuit(x): return qml.expval(qml.PauliZ(0)) x = np.array([1.3, 0.2]) - with pytest.raises(qml.wires.WireError, match=r"contain wires not found on the device: \{1\}"): + with pytest.raises(qml.wires.WireError, match=r"no free wire"): qml.metric_tensor(circuit)(x) From 25f412b8c04b6c1242ead1fc3a920c910729b5cb Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Mon, 5 May 2025 16:23:40 -0400 Subject: [PATCH 19/42] try: blocking final transforms --- pennylane/workflow/execution.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane/workflow/execution.py b/pennylane/workflow/execution.py index f77f15e19ef..07c418c104f 100644 --- a/pennylane/workflow/execution.py +++ b/pennylane/workflow/execution.py @@ -188,7 +188,7 @@ def cost_fn(params, x): ### Apply the user transforms #### user_post_processing = lambda x: x # null basically - if transform_program: + if transform_program and not transform_program.has_final_transform: tapes, user_post_processing = transform_program(tapes) if transform_program.is_informative: return user_post_processing(tapes) From dff2e4a9d2a85e9db18c30e8ef3b4f5e5330b129 Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Mon, 5 May 2025 16:53:01 -0400 Subject: [PATCH 20/42] revert regex match --- tests/gradients/core/test_metric_tensor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/gradients/core/test_metric_tensor.py b/tests/gradients/core/test_metric_tensor.py index c3b352f8c1a..e585a43483d 100644 --- a/tests/gradients/core/test_metric_tensor.py +++ b/tests/gradients/core/test_metric_tensor.py @@ -1560,7 +1560,7 @@ def circuit(x): return qml.expval(qml.PauliZ(0)) x = np.array([1.3, 0.2]) - with pytest.raises(qml.wires.WireError, match=r"no free wire"): + with pytest.raises(qml.wires.WireError, match=r"contain wires not found on the device: \{1\}"): qml.metric_tensor(circuit)(x) From e3f981e827e03df85b28c2fe5552f7e7c0872213 Mon Sep 17 00:00:00 2001 From: "Yushao Chen (Jerry)" Date: Tue, 6 May 2025 10:10:27 -0400 Subject: [PATCH 21/42] Update pennylane/workflow/execution.py Co-authored-by: Christina Lee --- pennylane/workflow/execution.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pennylane/workflow/execution.py b/pennylane/workflow/execution.py index 07c418c104f..19b09e3e7af 100644 --- a/pennylane/workflow/execution.py +++ b/pennylane/workflow/execution.py @@ -194,6 +194,9 @@ def cost_fn(params, x): return user_post_processing(tapes) transform_program = TransformProgram() + if not tapes: + return user_post_processing(()) + ### Specifying and preprocessing variables #### interface = _resolve_interface(interface, tapes) From a1cca48b0fcbdd1973bf18ab2561dcc49fa8ee9d Mon Sep 17 00:00:00 2001 From: "Yushao Chen (Jerry)" Date: Tue, 6 May 2025 10:10:37 -0400 Subject: [PATCH 22/42] Update pennylane/workflow/execution.py Co-authored-by: Christina Lee --- pennylane/workflow/execution.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pennylane/workflow/execution.py b/pennylane/workflow/execution.py index 19b09e3e7af..b62f9f5b0fb 100644 --- a/pennylane/workflow/execution.py +++ b/pennylane/workflow/execution.py @@ -187,12 +187,12 @@ def cost_fn(params, x): return () ### Apply the user transforms #### - user_post_processing = lambda x: x # null basically - if transform_program and not transform_program.has_final_transform: - tapes, user_post_processing = transform_program(tapes) - if transform_program.is_informative: - return user_post_processing(tapes) - transform_program = TransformProgram() + transform_program = transform_program or TransformProgram: + tapes, user_post_processing = transform_program(tapes) + if transform_program.is_informative: + return user_post_processing(tapes) + transform_program = TransformProgram() + if not tapes: return user_post_processing(()) From 2497b0890e699285968db39f76acef35d77dc2af Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Tue, 6 May 2025 10:29:46 -0400 Subject: [PATCH 23/42] debug --- pennylane/workflow/execution.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pennylane/workflow/execution.py b/pennylane/workflow/execution.py index b62f9f5b0fb..49b3dce54e2 100644 --- a/pennylane/workflow/execution.py +++ b/pennylane/workflow/execution.py @@ -187,13 +187,12 @@ def cost_fn(params, x): return () ### Apply the user transforms #### - transform_program = transform_program or TransformProgram: + transform_program = transform_program or TransformProgram() tapes, user_post_processing = transform_program(tapes) if transform_program.is_informative: return user_post_processing(tapes) transform_program = TransformProgram() - if not tapes: return user_post_processing(()) From 0f51cdcdf125cf1b033f96cb1d48b0e3f45b41e8 Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Tue, 6 May 2025 10:47:24 -0400 Subject: [PATCH 24/42] adjust hadamard test: cost10 [32, 3] to [8, 3] --- tests/gradients/core/test_hadamard_gradient.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/gradients/core/test_hadamard_gradient.py b/tests/gradients/core/test_hadamard_gradient.py index 048082d0dba..9c0dc3d0ec6 100755 --- a/tests/gradients/core/test_hadamard_gradient.py +++ b/tests/gradients/core/test_hadamard_gradient.py @@ -870,7 +870,7 @@ def test_output_shape_matches_qnode_expval_array(self, cost, exp_shape, exp_type (cost4, [4, 3], np.ndarray), (cost5, [4, 3], list), (cost6, [2, 4, 3], tuple), - (cost10, [32, 3], np.ndarray), # Note that the shape here depends on the device + (cost10, [8, 3], np.ndarray), # Note that the shape here depends on the device (cost11, [2, 32, 3], tuple), (cost12, [8, 3], np.ndarray), ] From 9400f916743abcf2a5adaa153fc89a2b077d4c67 Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Tue, 6 May 2025 10:47:35 -0400 Subject: [PATCH 25/42] regex pattern adjust --- tests/gradients/core/test_metric_tensor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/gradients/core/test_metric_tensor.py b/tests/gradients/core/test_metric_tensor.py index e585a43483d..c3b352f8c1a 100644 --- a/tests/gradients/core/test_metric_tensor.py +++ b/tests/gradients/core/test_metric_tensor.py @@ -1560,7 +1560,7 @@ def circuit(x): return qml.expval(qml.PauliZ(0)) x = np.array([1.3, 0.2]) - with pytest.raises(qml.wires.WireError, match=r"contain wires not found on the device: \{1\}"): + with pytest.raises(qml.wires.WireError, match=r"no free wire"): qml.metric_tensor(circuit)(x) From 0234f2b3a64cb8697c5b38c22e4a5f75be70c645 Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Tue, 6 May 2025 10:48:00 -0400 Subject: [PATCH 26/42] TEMPORARY: skip for now to check more tests --- tests/gradients/core/test_hadamard_gradient.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/gradients/core/test_hadamard_gradient.py b/tests/gradients/core/test_hadamard_gradient.py index 9c0dc3d0ec6..744bfffc917 100755 --- a/tests/gradients/core/test_hadamard_gradient.py +++ b/tests/gradients/core/test_hadamard_gradient.py @@ -871,7 +871,7 @@ def test_output_shape_matches_qnode_expval_array(self, cost, exp_shape, exp_type (cost5, [4, 3], list), (cost6, [2, 4, 3], tuple), (cost10, [8, 3], np.ndarray), # Note that the shape here depends on the device - (cost11, [2, 32, 3], tuple), + # (cost11, [2, 32, 3], tuple), (cost12, [8, 3], np.ndarray), ] From 1aa7cb2461f075f4e9e40c22f865fbc9e7448eed Mon Sep 17 00:00:00 2001 From: "Yushao Chen (Jerry)" Date: Tue, 6 May 2025 11:41:28 -0400 Subject: [PATCH 27/42] Update pennylane/workflow/execution.py Co-authored-by: Christina Lee --- pennylane/workflow/execution.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pennylane/workflow/execution.py b/pennylane/workflow/execution.py index 49b3dce54e2..051a5f74cf6 100644 --- a/pennylane/workflow/execution.py +++ b/pennylane/workflow/execution.py @@ -219,8 +219,7 @@ def cost_fn(params, x): #### Executing the configured setup ##### tapes, outer_post_processing = outer_transform(tapes) - if outer_transform.is_informative: - return user_post_processing(outer_post_processing(tapes)) + assert not outer_transform.is_informative, "should only contain device preprocessing" results = run(tapes, device, config, inner_transform) return user_post_processing(outer_post_processing(results)) From c5ca4e70526dcf236ccf3e7a097b7f7c4ff6df61 Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Tue, 6 May 2025 12:02:11 -0400 Subject: [PATCH 28/42] fix hadamard test: increase the wires 5->6 --- tests/gradients/core/test_hadamard_gradient.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/gradients/core/test_hadamard_gradient.py b/tests/gradients/core/test_hadamard_gradient.py index 744bfffc917..35580f9622b 100755 --- a/tests/gradients/core/test_hadamard_gradient.py +++ b/tests/gradients/core/test_hadamard_gradient.py @@ -871,7 +871,7 @@ def test_output_shape_matches_qnode_expval_array(self, cost, exp_shape, exp_type (cost5, [4, 3], list), (cost6, [2, 4, 3], tuple), (cost10, [8, 3], np.ndarray), # Note that the shape here depends on the device - # (cost11, [2, 32, 3], tuple), + (cost11, [2, 32, 3], tuple), (cost12, [8, 3], np.ndarray), ] @@ -881,7 +881,7 @@ def test_output_shape_matches_qnode_expval_array(self, cost, exp_shape, exp_type @pytest.mark.parametrize("cost, exp_shape, exp_type", costs_and_expected_probs) def test_output_shape_matches_qnode_probs(self, cost, exp_shape, exp_type, mode): """Test that the transform output shape matches that of the QNode.""" - dev = qml.device("default.qubit", wires=5) + dev = qml.device("default.qubit", wires=6) x = np.random.rand(3) circuit = qml.QNode(cost, dev) From e5cd276eaad6d4913afaf85a2a99e3b7966d7497 Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Tue, 6 May 2025 12:04:52 -0400 Subject: [PATCH 29/42] rm program from resolution step 1: rm from source only. See if we break anything --- pennylane/workflow/resolution.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/pennylane/workflow/resolution.py b/pennylane/workflow/resolution.py index 5f9fe55f88b..f4efc373a72 100644 --- a/pennylane/workflow/resolution.py +++ b/pennylane/workflow/resolution.py @@ -282,8 +282,6 @@ def _resolve_execution_config( if ( "lightning" in device.name - and transform_program - and qml.metric_tensor in transform_program and execution_config.gradient_method == "best" ): execution_config = replace(execution_config, gradient_method=qml.gradients.param_shift) From f367b0dfffde742006b4485a02b04d850a416069 Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Tue, 6 May 2025 12:25:48 -0400 Subject: [PATCH 30/42] step2: try purge --- .../workflow/construct_execution_config.py | 4 +--- pennylane/workflow/execution.py | 2 +- pennylane/workflow/resolution.py | 7 +----- .../interfaces/run/test_autograd_run.py | 8 +++---- .../interfaces/run/test_jax_jit_run.py | 8 +++---- tests/workflow/interfaces/run/test_jax_run.py | 8 +++---- .../run/test_tensorflow_autograph_run.py | 20 +++++------------ .../interfaces/run/test_tensorflow_run.py | 20 +++++------------ .../workflow/interfaces/run/test_torch_run.py | 8 +++---- .../workflow/test_resolve_execution_config.py | 22 +++++-------------- 10 files changed, 33 insertions(+), 74 deletions(-) diff --git a/pennylane/workflow/construct_execution_config.py b/pennylane/workflow/construct_execution_config.py index 4b0577501d3..cf95d303929 100644 --- a/pennylane/workflow/construct_execution_config.py +++ b/pennylane/workflow/construct_execution_config.py @@ -106,9 +106,7 @@ def wrapper(*args, **kwargs): if resolve: tape = construct_tape(qnode, level=0)(*args, **kwargs) # pylint:disable=protected-access - config = _resolve_execution_config( - config, qnode.device, (tape,), qnode._transform_program - ) + config = _resolve_execution_config(config, qnode.device, (tape,)) return config diff --git a/pennylane/workflow/execution.py b/pennylane/workflow/execution.py index 051a5f74cf6..dee7d5fc08e 100644 --- a/pennylane/workflow/execution.py +++ b/pennylane/workflow/execution.py @@ -209,7 +209,7 @@ def cost_fn(params, x): derivative_order=max_diff, executor_backend=executor_backend, ) - config = _resolve_execution_config(config, device, tapes, transform_program=transform_program) + config = _resolve_execution_config(config, device, tapes) transform_program = transform_program or qml.transforms.core.TransformProgram() outer_transform, inner_transform = _setup_transform_program( diff --git a/pennylane/workflow/resolution.py b/pennylane/workflow/resolution.py index f4efc373a72..770b482ac8a 100644 --- a/pennylane/workflow/resolution.py +++ b/pennylane/workflow/resolution.py @@ -260,7 +260,6 @@ def _resolve_execution_config( execution_config: "qml.devices.ExecutionConfig", device: "qml.devices.Device", tapes: QuantumScriptBatch, - transform_program: Optional[TransformProgram] = None, ) -> "qml.devices.ExecutionConfig": """Resolves the execution configuration for non-device specific properties. @@ -268,7 +267,6 @@ def _resolve_execution_config( execution_config (qml.devices.ExecutionConfig): an execution config to be executed on the device device (qml.devices.Device): a Pennylane device tapes (QuantumScriptBatch): a batch of tapes - transform_program (TransformProgram): a program of transformations to be applied to the tapes Returns: qml.devices.ExecutionConfig: resolved execution configuration @@ -280,10 +278,7 @@ def _resolve_execution_config( ): updated_values["grad_on_execution"] = False - if ( - "lightning" in device.name - and execution_config.gradient_method == "best" - ): + if "lightning" in device.name and execution_config.gradient_method == "best": execution_config = replace(execution_config, gradient_method=qml.gradients.param_shift) execution_config = _resolve_diff_method(execution_config, device, tape=tapes[0]) diff --git a/tests/workflow/interfaces/run/test_autograd_run.py b/tests/workflow/interfaces/run/test_autograd_run.py index f5bfe50f2bb..3febdf6b468 100644 --- a/tests/workflow/interfaces/run/test_autograd_run.py +++ b/tests/workflow/interfaces/run/test_autograd_run.py @@ -46,9 +46,7 @@ def cost(a, b): ops2 = [qml.RY(a, wires="a"), qml.RX(b, wires="a")] tape2 = qml.tape.QuantumScript(ops2, [qml.expval(qml.PauliZ("a"))], shots=shots) - resolved_config = _resolve_execution_config( - config, device, [tape1, tape2], TransformProgram() - ) + resolved_config = _resolve_execution_config(config, device, [tape1, tape2]) inner_tp = _setup_transform_program(TransformProgram(), device, resolved_config)[1] return run([tape1, tape2], device, resolved_config, inner_tp) @@ -80,7 +78,7 @@ def test_scalar_jacobian(self, device, config, shots, seed): def cost(a): tape = qml.tape.QuantumScript([qml.RY(a, 0)], [qml.expval(qml.PauliZ(0))], shots=shots) - resolved_config = _resolve_execution_config(config, device, [tape], TransformProgram()) + resolved_config = _resolve_execution_config(config, device, [tape]) inner_tp = _setup_transform_program(TransformProgram(), device, resolved_config)[1] return run([tape], device, resolved_config, inner_tp)[0] @@ -106,7 +104,7 @@ def cost(a, b): ops = [qml.RY(a, wires=0), qml.RX(b, wires=1), qml.CNOT(wires=[0, 1])] m = [qml.expval(qml.PauliZ(0)), qml.expval(qml.PauliY(1))] tape = qml.tape.QuantumScript(ops, m, shots=shots) - resolved_config = _resolve_execution_config(config, device, [tape], TransformProgram()) + resolved_config = _resolve_execution_config(config, device, [tape]) inner_tp = _setup_transform_program(TransformProgram(), device, resolved_config)[1] return autograd.numpy.hstack(run([tape], device, resolved_config, inner_tp)[0]) diff --git a/tests/workflow/interfaces/run/test_jax_jit_run.py b/tests/workflow/interfaces/run/test_jax_jit_run.py index 85f7fa894fe..c59b68890f8 100644 --- a/tests/workflow/interfaces/run/test_jax_jit_run.py +++ b/tests/workflow/interfaces/run/test_jax_jit_run.py @@ -53,9 +53,7 @@ def cost(a, b): ops2 = [qml.RY(a, wires="a"), qml.RX(b, wires="a")] tape2 = qml.tape.QuantumScript(ops2, [qml.expval(qml.PauliZ("a"))], shots=shots) - resolved_config = _resolve_execution_config( - config, device, [tape1, tape2], TransformProgram() - ) + resolved_config = _resolve_execution_config(config, device, [tape1, tape2]) inner_tp = _setup_transform_program(TransformProgram(), device, resolved_config)[1] return run([tape1, tape2], device, resolved_config, inner_tp) @@ -87,7 +85,7 @@ def test_scalar_jacobian(self, device, config, shots, seed): def cost(a): tape = qml.tape.QuantumScript([qml.RY(a, 0)], [qml.expval(qml.PauliZ(0))], shots=shots) - resolved_config = _resolve_execution_config(config, device, [tape], TransformProgram()) + resolved_config = _resolve_execution_config(config, device, [tape]) inner_tp = _setup_transform_program(TransformProgram(), device, resolved_config)[1] return run([tape], device, resolved_config, inner_tp)[0] @@ -112,7 +110,7 @@ def cost(a, b): m = [qml.expval(qml.PauliZ(0)), qml.expval(qml.PauliY(1))] tape = qml.tape.QuantumScript(ops, m, shots=shots) - resolved_config = _resolve_execution_config(config, device, [tape], TransformProgram()) + resolved_config = _resolve_execution_config(config, device, [tape]) inner_tp = _setup_transform_program(TransformProgram(), device, resolved_config)[1] return run([tape], device, resolved_config, inner_tp)[0] diff --git a/tests/workflow/interfaces/run/test_jax_run.py b/tests/workflow/interfaces/run/test_jax_run.py index 6dfd7a0dae8..950393484d0 100644 --- a/tests/workflow/interfaces/run/test_jax_run.py +++ b/tests/workflow/interfaces/run/test_jax_run.py @@ -48,9 +48,7 @@ def cost(a, b): ops2 = [qml.RY(a, wires="a"), qml.RX(b, wires="a")] tape2 = qml.tape.QuantumScript(ops2, [qml.expval(qml.PauliZ("a"))], shots=shots) - resolved_config = _resolve_execution_config( - config, device, [tape1, tape2], TransformProgram() - ) + resolved_config = _resolve_execution_config(config, device, [tape1, tape2]) inner_tp = _setup_transform_program(TransformProgram(), device, resolved_config)[1] return run([tape1, tape2], device, resolved_config, inner_tp) @@ -82,7 +80,7 @@ def test_scalar_jacobian(self, device, config, shots, seed): def cost(a): tape = qml.tape.QuantumScript([qml.RY(a, 0)], [qml.expval(qml.PauliZ(0))], shots=shots) - resolved_config = _resolve_execution_config(config, device, [tape], TransformProgram()) + resolved_config = _resolve_execution_config(config, device, [tape]) inner_tp = _setup_transform_program(TransformProgram(), device, resolved_config)[1] return run([tape], device, resolved_config, inner_tp)[0] @@ -107,7 +105,7 @@ def cost(a, b): m = [qml.expval(qml.PauliZ(0)), qml.expval(qml.PauliY(1))] tape = qml.tape.QuantumScript(ops, m, shots=shots) - resolved_config = _resolve_execution_config(config, device, [tape], TransformProgram()) + resolved_config = _resolve_execution_config(config, device, [tape]) inner_tp = _setup_transform_program(TransformProgram(), device, resolved_config)[1] return run([tape], device, resolved_config, inner_tp)[0] diff --git a/tests/workflow/interfaces/run/test_tensorflow_autograph_run.py b/tests/workflow/interfaces/run/test_tensorflow_autograph_run.py index c106f668a39..400482cd963 100644 --- a/tests/workflow/interfaces/run/test_tensorflow_autograph_run.py +++ b/tests/workflow/interfaces/run/test_tensorflow_autograph_run.py @@ -42,9 +42,7 @@ def test_run(self, device, config, shots, seed): device = get_device(device, seed=seed) config = replace(config, interface="tf-autograph") - resolved_config = _resolve_execution_config( - config, device, [QuantumScript()], TransformProgram() - ) + resolved_config = _resolve_execution_config(config, device, [QuantumScript()]) def cost(a, b): ops1 = [qml.RY(a, wires=0), qml.RX(b, wires=0)] @@ -53,9 +51,7 @@ def cost(a, b): ops2 = [qml.RY(a, wires="a"), qml.RX(b, wires="a")] tape2 = qml.tape.QuantumScript(ops2, [qml.expval(qml.PauliZ("a"))], shots=shots) - resolved_config = _resolve_execution_config( - config, device, [tape1, tape2], TransformProgram() - ) + resolved_config = _resolve_execution_config(config, device, [tape1, tape2]) inner_tp = _setup_transform_program(TransformProgram(), device, resolved_config)[1] return run([tape1, tape2], device, resolved_config, inner_tp) @@ -86,14 +82,12 @@ def test_scalar_jacobian(self, device, config, shots, seed): pytest.xfail(reason="Partitioned shots are not supported yet.") device = get_device(device, seed=seed) config = replace(config, interface="tf-autograph") - resolved_config = _resolve_execution_config( - config, device, [QuantumScript()], TransformProgram() - ) + resolved_config = _resolve_execution_config(config, device, [QuantumScript()]) device_vjp = resolved_config.use_device_jacobian_product def cost(a): tape = qml.tape.QuantumScript([qml.RY(a, 0)], [qml.expval(qml.PauliZ(0))], shots=shots) - resolved_config = _resolve_execution_config(config, device, [tape], TransformProgram()) + resolved_config = _resolve_execution_config(config, device, [tape]) inner_tp = _setup_transform_program(TransformProgram(), device, resolved_config)[1] return run([tape], device, resolved_config, inner_tp)[0] @@ -118,16 +112,14 @@ def test_jacobian(self, device, config, shots, seed): config = replace(config, interface="tf-autograph") device = get_device(device, seed=seed) - resolved_config = _resolve_execution_config( - config, device, [QuantumScript()], TransformProgram() - ) + resolved_config = _resolve_execution_config(config, device, [QuantumScript()]) device_vjp = resolved_config.use_device_jacobian_product def cost(a, b): ops = [qml.RY(a, wires=0), qml.RX(b, wires=1), qml.CNOT(wires=[0, 1])] m = [qml.expval(qml.PauliZ(0)), qml.expval(qml.PauliY(1))] tape = qml.tape.QuantumScript(ops, m, shots=shots) - resolved_config = _resolve_execution_config(config, device, [tape], TransformProgram()) + resolved_config = _resolve_execution_config(config, device, [tape]) inner_tp = _setup_transform_program(TransformProgram(), device, resolved_config)[1] return qml.math.hstack( run([tape], device, resolved_config, inner_tp)[0], like="tensorflow" diff --git a/tests/workflow/interfaces/run/test_tensorflow_run.py b/tests/workflow/interfaces/run/test_tensorflow_run.py index 0114b66016f..1ab8213179f 100644 --- a/tests/workflow/interfaces/run/test_tensorflow_run.py +++ b/tests/workflow/interfaces/run/test_tensorflow_run.py @@ -39,9 +39,7 @@ def test_run(self, device, config, shots, seed): """Test execution of tapes on 'tensorflow' interface.""" device = get_device(device, seed=seed) config = replace(config, interface="tensorflow") - resolved_config = _resolve_execution_config( - config, device, [QuantumScript()], TransformProgram() - ) + resolved_config = _resolve_execution_config(config, device, [QuantumScript()]) def cost(a, b): ops1 = [qml.RY(a, wires=0), qml.RX(b, wires=0)] @@ -50,9 +48,7 @@ def cost(a, b): ops2 = [qml.RY(a, wires="a"), qml.RX(b, wires="a")] tape2 = qml.tape.QuantumScript(ops2, [qml.expval(qml.PauliZ("a"))], shots=shots) - resolved_config = _resolve_execution_config( - config, device, [tape1, tape2], TransformProgram() - ) + resolved_config = _resolve_execution_config(config, device, [tape1, tape2]) print(resolved_config.use_device_jacobian_product) inner_tp = _setup_transform_program(TransformProgram(), device, resolved_config)[1] return run([tape1, tape2], device, resolved_config, inner_tp) @@ -87,14 +83,12 @@ def test_scalar_jacobian(self, device, config, shots, seed): pytest.xfail(reason="Partitioned shots are not supported yet.") device = get_device(device, seed=seed) config = replace(config, interface="tensorflow") - resolved_config = _resolve_execution_config( - config, device, [QuantumScript()], TransformProgram() - ) + resolved_config = _resolve_execution_config(config, device, [QuantumScript()]) device_vjp = resolved_config.use_device_jacobian_product def cost(a): tape = qml.tape.QuantumScript([qml.RY(a, 0)], [qml.expval(qml.PauliZ(0))], shots=shots) - resolved_config = _resolve_execution_config(config, device, [tape], TransformProgram()) + resolved_config = _resolve_execution_config(config, device, [tape]) inner_tp = _setup_transform_program(TransformProgram(), device, resolved_config)[1] return run([tape], device, resolved_config, inner_tp)[0] @@ -117,16 +111,14 @@ def test_jacobian(self, device, config, shots, seed): device = get_device(device, seed=seed) config = replace(config, interface="tensorflow") - resolved_config = _resolve_execution_config( - config, device, [QuantumScript()], TransformProgram() - ) + resolved_config = _resolve_execution_config(config, device, [QuantumScript()]) device_vjp = resolved_config.use_device_jacobian_product def cost(a, b): ops = [qml.RY(a, wires=0), qml.RX(b, wires=1), qml.CNOT(wires=[0, 1])] m = [qml.expval(qml.PauliZ(0)), qml.expval(qml.PauliY(1))] tape = qml.tape.QuantumScript(ops, m, shots=shots) - resolved_config = _resolve_execution_config(config, device, [tape], TransformProgram()) + resolved_config = _resolve_execution_config(config, device, [tape]) inner_tp = _setup_transform_program(TransformProgram(), device, resolved_config)[1] return qml.math.hstack( run([tape], device, resolved_config, inner_tp)[0], like="tensorflow" diff --git a/tests/workflow/interfaces/run/test_torch_run.py b/tests/workflow/interfaces/run/test_torch_run.py index 1da6f17ff63..2e102152034 100644 --- a/tests/workflow/interfaces/run/test_torch_run.py +++ b/tests/workflow/interfaces/run/test_torch_run.py @@ -51,9 +51,7 @@ def cost(a, b): ops2 = [qml.RY(a, wires="a"), qml.RX(b, wires="a")] tape2 = qml.tape.QuantumScript(ops2, [qml.expval(qml.PauliZ("a"))], shots=shots) - resolved_config = _resolve_execution_config( - config, device, [tape1, tape2], TransformProgram() - ) + resolved_config = _resolve_execution_config(config, device, [tape1, tape2]) inner_tp = _setup_transform_program(TransformProgram(), device, resolved_config)[1] return run([tape1, tape2], device, resolved_config, inner_tp) @@ -91,7 +89,7 @@ def test_scalar_jacobian(self, device, config, shots, seed): def cost(a): tape = qml.tape.QuantumScript([qml.RY(a, 0)], [qml.expval(qml.PauliZ(0))], shots=shots) - resolved_config = _resolve_execution_config(config, device, [tape], TransformProgram()) + resolved_config = _resolve_execution_config(config, device, [tape]) _, inner_tp = _setup_transform_program(TransformProgram(), device, resolved_config) return run([tape], device, resolved_config, inner_tp)[0] @@ -122,7 +120,7 @@ def cost(a, b): m = [qml.expval(qml.PauliZ(0)), qml.expval(qml.PauliY(1))] tape = qml.tape.QuantumScript(ops, m, shots=shots) - resolved_config = _resolve_execution_config(config, device, [tape], TransformProgram()) + resolved_config = _resolve_execution_config(config, device, [tape]) _, inner_tp = _setup_transform_program(TransformProgram(), device, resolved_config) res = run([tape], device, resolved_config, inner_tp)[0] diff --git a/tests/workflow/test_resolve_execution_config.py b/tests/workflow/test_resolve_execution_config.py index 96e7cb9f595..f858c754ec3 100644 --- a/tests/workflow/test_resolve_execution_config.py +++ b/tests/workflow/test_resolve_execution_config.py @@ -28,9 +28,8 @@ def test_resolve_execution_config_with_gradient_method(): device = qml.device("default.qubit") empty_tape = qml.tape.QuantumScript([], [qml.expval(qml.Z(0))]) - empty_tp = TransformProgram() - resolved_config = _resolve_execution_config(execution_config, device, [empty_tape], empty_tp) + resolved_config = _resolve_execution_config(execution_config, device, [empty_tape]) assert resolved_config.gradient_method == "backprop" @@ -43,11 +42,8 @@ def test_metric_tensor_lightning_edge_case(): device = qml.device("lightning.qubit", wires=2) empty_tape = qml.tape.QuantumScript([], [qml.expval(qml.Z(0))]) - metric_tensor_tp = TransformProgram([qml.metric_tensor]) - resolved_config = _resolve_execution_config( - execution_config, device, [empty_tape], metric_tensor_tp - ) + resolved_config = _resolve_execution_config(execution_config, device, [empty_tape]) assert resolved_config.gradient_method is qml.gradients.param_shift @@ -57,9 +53,8 @@ def test_param_shift_cv_kwargs(): dev = qml.device("default.gaussian", wires=1) tape = qml.tape.QuantumScript([qml.Displacement(0.5, 0.0, wires=0)]) execution_config = ExecutionConfig(gradient_method="parameter-shift") - empty_tp = TransformProgram() - resolved_config = _resolve_execution_config(execution_config, dev, [tape], empty_tp) + resolved_config = _resolve_execution_config(execution_config, dev, [tape]) assert resolved_config.gradient_keyword_arguments["dev"] == dev @@ -71,9 +66,8 @@ def test_mcm_config_validation(): device = qml.device("default.qubit") empty_tape = qml.tape.QuantumScript([], [qml.expval(qml.Z(0))]) - empty_tp = TransformProgram() - resolved_config = _resolve_execution_config(execution_config, device, [empty_tape], empty_tp) + resolved_config = _resolve_execution_config(execution_config, device, [empty_tape]) expected_mcm_config = MCMConfig(postselect_mode=None) @@ -90,11 +84,8 @@ def test_jax_interface(mcm_method, postselect_mode): device = qml.device("default.qubit") tape_with_finite_shots = qml.tape.QuantumScript([], [qml.expval(qml.Z(0))], shots=100) - empty_tp = TransformProgram() - resolved_config = _resolve_execution_config( - execution_config, device, [tape_with_finite_shots], empty_tp - ) + resolved_config = _resolve_execution_config(execution_config, device, [tape_with_finite_shots]) expected_mcm_config = MCMConfig(mcm_method, postselect_mode="pad-invalid-samples") @@ -109,9 +100,8 @@ def test_jax_jit_interface(): device = qml.device("default.qubit") empty_tape = qml.tape.QuantumScript([], [qml.expval(qml.Z(0))]) - empty_tp = TransformProgram() - resolved_config = _resolve_execution_config(execution_config, device, [empty_tape], empty_tp) + resolved_config = _resolve_execution_config(execution_config, device, [empty_tape]) expected_mcm_config = MCMConfig(mcm_method="deferred", postselect_mode="fill-shots") From eab941d416590a2c3a76bc0149cfdc2a38054540 Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Tue, 6 May 2025 13:51:41 -0400 Subject: [PATCH 31/42] del remains --- pennylane/workflow/resolution.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/pennylane/workflow/resolution.py b/pennylane/workflow/resolution.py index 770b482ac8a..a9763d2425d 100644 --- a/pennylane/workflow/resolution.py +++ b/pennylane/workflow/resolution.py @@ -278,8 +278,6 @@ def _resolve_execution_config( ): updated_values["grad_on_execution"] = False - if "lightning" in device.name and execution_config.gradient_method == "best": - execution_config = replace(execution_config, gradient_method=qml.gradients.param_shift) execution_config = _resolve_diff_method(execution_config, device, tape=tapes[0]) if execution_config.use_device_jacobian_product and not device.supports_vjp( From 5e5c6671ce7d0b68098e4747f962f2c9ca8de471 Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Tue, 6 May 2025 14:09:18 -0400 Subject: [PATCH 32/42] remove unused --- pennylane/workflow/resolution.py | 4 ++-- tests/workflow/test_resolve_execution_config.py | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/pennylane/workflow/resolution.py b/pennylane/workflow/resolution.py index a9763d2425d..fbb6aef32de 100644 --- a/pennylane/workflow/resolution.py +++ b/pennylane/workflow/resolution.py @@ -17,7 +17,7 @@ from dataclasses import replace from importlib.metadata import version from importlib.util import find_spec -from typing import Literal, Optional, Union, get_args +from typing import Literal, Union, get_args from warnings import warn from packaging.version import Version @@ -26,7 +26,7 @@ from pennylane.logging import debug_logger from pennylane.math import Interface, get_canonical_interface_name, get_interface from pennylane.tape import QuantumScriptBatch -from pennylane.transforms.core import TransformDispatcher, TransformProgram +from pennylane.transforms.core import TransformDispatcher SupportedDiffMethods = Literal[ None, diff --git a/tests/workflow/test_resolve_execution_config.py b/tests/workflow/test_resolve_execution_config.py index f858c754ec3..c266de5b174 100644 --- a/tests/workflow/test_resolve_execution_config.py +++ b/tests/workflow/test_resolve_execution_config.py @@ -18,7 +18,6 @@ import pennylane as qml from pennylane.devices import ExecutionConfig, MCMConfig -from pennylane.transforms.core import TransformProgram from pennylane.workflow.resolution import _resolve_execution_config From fe06bcfbb9d0c7096155a253d11343d943e3088c Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Tue, 6 May 2025 14:15:15 -0400 Subject: [PATCH 33/42] partial revert to fix test: keep lighnting conditional --- pennylane/workflow/resolution.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pennylane/workflow/resolution.py b/pennylane/workflow/resolution.py index fbb6aef32de..c6effa12a50 100644 --- a/pennylane/workflow/resolution.py +++ b/pennylane/workflow/resolution.py @@ -277,7 +277,8 @@ def _resolve_execution_config( execution_config.gradient_method, Callable ): updated_values["grad_on_execution"] = False - + if "lightning" in device.name: + execution_config = replace(execution_config, gradient_method=qml.gradients.param_shift) execution_config = _resolve_diff_method(execution_config, device, tape=tapes[0]) if execution_config.use_device_jacobian_product and not device.supports_vjp( From c4639f1c0343381b66544d9bcda3d25d643f8027 Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Tue, 6 May 2025 14:32:50 -0400 Subject: [PATCH 34/42] revert the revert --- pennylane/workflow/resolution.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/pennylane/workflow/resolution.py b/pennylane/workflow/resolution.py index c6effa12a50..1586053fc67 100644 --- a/pennylane/workflow/resolution.py +++ b/pennylane/workflow/resolution.py @@ -277,8 +277,6 @@ def _resolve_execution_config( execution_config.gradient_method, Callable ): updated_values["grad_on_execution"] = False - if "lightning" in device.name: - execution_config = replace(execution_config, gradient_method=qml.gradients.param_shift) execution_config = _resolve_diff_method(execution_config, device, tape=tapes[0]) if execution_config.use_device_jacobian_product and not device.supports_vjp( From 62cc0bfab00ca2972499e68d4dea32db7317e9ba Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Tue, 6 May 2025 14:33:10 -0400 Subject: [PATCH 35/42] and adjust the test instead --- tests/workflow/test_resolve_execution_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/workflow/test_resolve_execution_config.py b/tests/workflow/test_resolve_execution_config.py index c266de5b174..f8c569b614f 100644 --- a/tests/workflow/test_resolve_execution_config.py +++ b/tests/workflow/test_resolve_execution_config.py @@ -44,7 +44,7 @@ def test_metric_tensor_lightning_edge_case(): resolved_config = _resolve_execution_config(execution_config, device, [empty_tape]) - assert resolved_config.gradient_method is qml.gradients.param_shift + assert resolved_config.gradient_method == "adjoint" def test_param_shift_cv_kwargs(): From a85018c5e90fb2d32da150442cdbb73e8f5dfc83 Mon Sep 17 00:00:00 2001 From: "Yushao Chen (Jerry)" Date: Wed, 7 May 2025 08:19:15 -0400 Subject: [PATCH 36/42] del unused Co-authored-by: Christina Lee --- pennylane/transforms/set_shots.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/pennylane/transforms/set_shots.py b/pennylane/transforms/set_shots.py index 0363578bb30..4c80ce135f1 100644 --- a/pennylane/transforms/set_shots.py +++ b/pennylane/transforms/set_shots.py @@ -57,6 +57,3 @@ def set_shots( if tape.shots != Shots(shots): tape = tape.copy(shots=shots) return (tape,), null_postprocessing - - -set_shots.is_user_transform = True From 91c65e595fe8bdb641b5133c50fee623cddd7693 Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Wed, 7 May 2025 09:43:55 -0400 Subject: [PATCH 37/42] rm tp from setup --- .../workflow/_setup_transform_program.py | 5 +--- pennylane/workflow/execution.py | 3 +-- .../interfaces/run/test_autograd_run.py | 6 ++--- .../interfaces/run/test_jax_jit_run.py | 6 ++--- tests/workflow/interfaces/run/test_jax_run.py | 6 ++--- .../run/test_tensorflow_autograph_run.py | 6 ++--- .../interfaces/run/test_tensorflow_run.py | 6 ++--- .../workflow/interfaces/run/test_torch_run.py | 6 ++--- .../workflow/test_setup_transform_program.py | 23 ++++++++----------- 9 files changed, 30 insertions(+), 37 deletions(-) diff --git a/pennylane/workflow/_setup_transform_program.py b/pennylane/workflow/_setup_transform_program.py index cebe728a787..c33f0087d57 100644 --- a/pennylane/workflow/_setup_transform_program.py +++ b/pennylane/workflow/_setup_transform_program.py @@ -63,7 +63,6 @@ def _prune_dynamic_transform(outer_transform, inner_transform): def _setup_transform_program( - user_transform_program: TransformProgram, device: "qml.devices.Device", resolved_execution_config: "qml.devices.ExecutionConfig", cache=None, @@ -85,9 +84,7 @@ def _setup_transform_program( device_transform_program = device.preprocess_transforms(resolved_execution_config) - outer_transform_program = qml.transforms.core.TransformProgram( - user_transform_program, cotransform_cache=user_transform_program.cotransform_cache - ) + outer_transform_program = qml.transforms.core.TransformProgram() inner_transform_program = qml.transforms.core.TransformProgram() # Add the gradient expand to the program if necessary diff --git a/pennylane/workflow/execution.py b/pennylane/workflow/execution.py index dee7d5fc08e..c26db03d47f 100644 --- a/pennylane/workflow/execution.py +++ b/pennylane/workflow/execution.py @@ -211,9 +211,8 @@ def cost_fn(params, x): ) config = _resolve_execution_config(config, device, tapes) - transform_program = transform_program or qml.transforms.core.TransformProgram() outer_transform, inner_transform = _setup_transform_program( - transform_program, device, config, cache, cachesize + device, config, cache, cachesize ) #### Executing the configured setup ##### diff --git a/tests/workflow/interfaces/run/test_autograd_run.py b/tests/workflow/interfaces/run/test_autograd_run.py index 3febdf6b468..23beb77b5ec 100644 --- a/tests/workflow/interfaces/run/test_autograd_run.py +++ b/tests/workflow/interfaces/run/test_autograd_run.py @@ -47,7 +47,7 @@ def cost(a, b): tape2 = qml.tape.QuantumScript(ops2, [qml.expval(qml.PauliZ("a"))], shots=shots) resolved_config = _resolve_execution_config(config, device, [tape1, tape2]) - inner_tp = _setup_transform_program(TransformProgram(), device, resolved_config)[1] + inner_tp = _setup_transform_program(device, resolved_config)[1] return run([tape1, tape2], device, resolved_config, inner_tp) a = pnp.array(0.1, requires_grad=True) @@ -79,7 +79,7 @@ def test_scalar_jacobian(self, device, config, shots, seed): def cost(a): tape = qml.tape.QuantumScript([qml.RY(a, 0)], [qml.expval(qml.PauliZ(0))], shots=shots) resolved_config = _resolve_execution_config(config, device, [tape]) - inner_tp = _setup_transform_program(TransformProgram(), device, resolved_config)[1] + inner_tp = _setup_transform_program(device, resolved_config)[1] return run([tape], device, resolved_config, inner_tp)[0] a = pnp.array(0.1, requires_grad=True) @@ -105,7 +105,7 @@ def cost(a, b): m = [qml.expval(qml.PauliZ(0)), qml.expval(qml.PauliY(1))] tape = qml.tape.QuantumScript(ops, m, shots=shots) resolved_config = _resolve_execution_config(config, device, [tape]) - inner_tp = _setup_transform_program(TransformProgram(), device, resolved_config)[1] + inner_tp = _setup_transform_program(device, resolved_config)[1] return autograd.numpy.hstack(run([tape], device, resolved_config, inner_tp)[0]) a = pnp.array(0.1, requires_grad=True) diff --git a/tests/workflow/interfaces/run/test_jax_jit_run.py b/tests/workflow/interfaces/run/test_jax_jit_run.py index c59b68890f8..d18630d591a 100644 --- a/tests/workflow/interfaces/run/test_jax_jit_run.py +++ b/tests/workflow/interfaces/run/test_jax_jit_run.py @@ -54,7 +54,7 @@ def cost(a, b): tape2 = qml.tape.QuantumScript(ops2, [qml.expval(qml.PauliZ("a"))], shots=shots) resolved_config = _resolve_execution_config(config, device, [tape1, tape2]) - inner_tp = _setup_transform_program(TransformProgram(), device, resolved_config)[1] + inner_tp = _setup_transform_program(device, resolved_config)[1] return run([tape1, tape2], device, resolved_config, inner_tp) a = jnp.array(0.1) @@ -86,7 +86,7 @@ def test_scalar_jacobian(self, device, config, shots, seed): def cost(a): tape = qml.tape.QuantumScript([qml.RY(a, 0)], [qml.expval(qml.PauliZ(0))], shots=shots) resolved_config = _resolve_execution_config(config, device, [tape]) - inner_tp = _setup_transform_program(TransformProgram(), device, resolved_config)[1] + inner_tp = _setup_transform_program(device, resolved_config)[1] return run([tape], device, resolved_config, inner_tp)[0] a = jnp.array(0.1) @@ -111,7 +111,7 @@ def cost(a, b): tape = qml.tape.QuantumScript(ops, m, shots=shots) resolved_config = _resolve_execution_config(config, device, [tape]) - inner_tp = _setup_transform_program(TransformProgram(), device, resolved_config)[1] + inner_tp = _setup_transform_program(device, resolved_config)[1] return run([tape], device, resolved_config, inner_tp)[0] a = jnp.array(0.1) diff --git a/tests/workflow/interfaces/run/test_jax_run.py b/tests/workflow/interfaces/run/test_jax_run.py index 950393484d0..516bfbea52f 100644 --- a/tests/workflow/interfaces/run/test_jax_run.py +++ b/tests/workflow/interfaces/run/test_jax_run.py @@ -49,7 +49,7 @@ def cost(a, b): tape2 = qml.tape.QuantumScript(ops2, [qml.expval(qml.PauliZ("a"))], shots=shots) resolved_config = _resolve_execution_config(config, device, [tape1, tape2]) - inner_tp = _setup_transform_program(TransformProgram(), device, resolved_config)[1] + inner_tp = _setup_transform_program(device, resolved_config)[1] return run([tape1, tape2], device, resolved_config, inner_tp) a = jnp.array(0.1) @@ -81,7 +81,7 @@ def test_scalar_jacobian(self, device, config, shots, seed): def cost(a): tape = qml.tape.QuantumScript([qml.RY(a, 0)], [qml.expval(qml.PauliZ(0))], shots=shots) resolved_config = _resolve_execution_config(config, device, [tape]) - inner_tp = _setup_transform_program(TransformProgram(), device, resolved_config)[1] + inner_tp = _setup_transform_program(device, resolved_config)[1] return run([tape], device, resolved_config, inner_tp)[0] a = jnp.array(0.1) @@ -106,7 +106,7 @@ def cost(a, b): tape = qml.tape.QuantumScript(ops, m, shots=shots) resolved_config = _resolve_execution_config(config, device, [tape]) - inner_tp = _setup_transform_program(TransformProgram(), device, resolved_config)[1] + inner_tp = _setup_transform_program(device, resolved_config)[1] return run([tape], device, resolved_config, inner_tp)[0] a = jnp.array(0.1) diff --git a/tests/workflow/interfaces/run/test_tensorflow_autograph_run.py b/tests/workflow/interfaces/run/test_tensorflow_autograph_run.py index 400482cd963..f8a88dd53f6 100644 --- a/tests/workflow/interfaces/run/test_tensorflow_autograph_run.py +++ b/tests/workflow/interfaces/run/test_tensorflow_autograph_run.py @@ -52,7 +52,7 @@ def cost(a, b): tape2 = qml.tape.QuantumScript(ops2, [qml.expval(qml.PauliZ("a"))], shots=shots) resolved_config = _resolve_execution_config(config, device, [tape1, tape2]) - inner_tp = _setup_transform_program(TransformProgram(), device, resolved_config)[1] + inner_tp = _setup_transform_program(device, resolved_config)[1] return run([tape1, tape2], device, resolved_config, inner_tp) a = tf.Variable(0.1, dtype="float64") @@ -88,7 +88,7 @@ def test_scalar_jacobian(self, device, config, shots, seed): def cost(a): tape = qml.tape.QuantumScript([qml.RY(a, 0)], [qml.expval(qml.PauliZ(0))], shots=shots) resolved_config = _resolve_execution_config(config, device, [tape]) - inner_tp = _setup_transform_program(TransformProgram(), device, resolved_config)[1] + inner_tp = _setup_transform_program(device, resolved_config)[1] return run([tape], device, resolved_config, inner_tp)[0] a = tf.Variable(0.1, dtype=tf.float64) @@ -120,7 +120,7 @@ def cost(a, b): m = [qml.expval(qml.PauliZ(0)), qml.expval(qml.PauliY(1))] tape = qml.tape.QuantumScript(ops, m, shots=shots) resolved_config = _resolve_execution_config(config, device, [tape]) - inner_tp = _setup_transform_program(TransformProgram(), device, resolved_config)[1] + inner_tp = _setup_transform_program(device, resolved_config)[1] return qml.math.hstack( run([tape], device, resolved_config, inner_tp)[0], like="tensorflow" ) diff --git a/tests/workflow/interfaces/run/test_tensorflow_run.py b/tests/workflow/interfaces/run/test_tensorflow_run.py index 1ab8213179f..01ba55a39f2 100644 --- a/tests/workflow/interfaces/run/test_tensorflow_run.py +++ b/tests/workflow/interfaces/run/test_tensorflow_run.py @@ -50,7 +50,7 @@ def cost(a, b): resolved_config = _resolve_execution_config(config, device, [tape1, tape2]) print(resolved_config.use_device_jacobian_product) - inner_tp = _setup_transform_program(TransformProgram(), device, resolved_config)[1] + inner_tp = _setup_transform_program(device, resolved_config)[1] return run([tape1, tape2], device, resolved_config, inner_tp) a = tf.Variable(0.1, dtype="float64") @@ -89,7 +89,7 @@ def test_scalar_jacobian(self, device, config, shots, seed): def cost(a): tape = qml.tape.QuantumScript([qml.RY(a, 0)], [qml.expval(qml.PauliZ(0))], shots=shots) resolved_config = _resolve_execution_config(config, device, [tape]) - inner_tp = _setup_transform_program(TransformProgram(), device, resolved_config)[1] + inner_tp = _setup_transform_program(device, resolved_config)[1] return run([tape], device, resolved_config, inner_tp)[0] a = tf.Variable(0.1, dtype=tf.float64) @@ -119,7 +119,7 @@ def cost(a, b): m = [qml.expval(qml.PauliZ(0)), qml.expval(qml.PauliY(1))] tape = qml.tape.QuantumScript(ops, m, shots=shots) resolved_config = _resolve_execution_config(config, device, [tape]) - inner_tp = _setup_transform_program(TransformProgram(), device, resolved_config)[1] + inner_tp = _setup_transform_program(device, resolved_config)[1] return qml.math.hstack( run([tape], device, resolved_config, inner_tp)[0], like="tensorflow" ) diff --git a/tests/workflow/interfaces/run/test_torch_run.py b/tests/workflow/interfaces/run/test_torch_run.py index 2e102152034..4ea7c1fa9b4 100644 --- a/tests/workflow/interfaces/run/test_torch_run.py +++ b/tests/workflow/interfaces/run/test_torch_run.py @@ -52,7 +52,7 @@ def cost(a, b): tape2 = qml.tape.QuantumScript(ops2, [qml.expval(qml.PauliZ("a"))], shots=shots) resolved_config = _resolve_execution_config(config, device, [tape1, tape2]) - inner_tp = _setup_transform_program(TransformProgram(), device, resolved_config)[1] + inner_tp = _setup_transform_program(device, resolved_config)[1] return run([tape1, tape2], device, resolved_config, inner_tp) a = torch.tensor(0.1, requires_grad=True) @@ -90,7 +90,7 @@ def test_scalar_jacobian(self, device, config, shots, seed): def cost(a): tape = qml.tape.QuantumScript([qml.RY(a, 0)], [qml.expval(qml.PauliZ(0))], shots=shots) resolved_config = _resolve_execution_config(config, device, [tape]) - _, inner_tp = _setup_transform_program(TransformProgram(), device, resolved_config) + _, inner_tp = _setup_transform_program(device, resolved_config) return run([tape], device, resolved_config, inner_tp)[0] a = torch.tensor(0.1, requires_grad=True) @@ -121,7 +121,7 @@ def cost(a, b): tape = qml.tape.QuantumScript(ops, m, shots=shots) resolved_config = _resolve_execution_config(config, device, [tape]) - _, inner_tp = _setup_transform_program(TransformProgram(), device, resolved_config) + _, inner_tp = _setup_transform_program(device, resolved_config) res = run([tape], device, resolved_config, inner_tp)[0] if shots.has_partitioned_shots: diff --git a/tests/workflow/test_setup_transform_program.py b/tests/workflow/test_setup_transform_program.py index 20f209d436c..827b0bbd2c9 100644 --- a/tests/workflow/test_setup_transform_program.py +++ b/tests/workflow/test_setup_transform_program.py @@ -50,9 +50,7 @@ def test_gradient_expand_transform(): device = qml.device("default.qubit") - container = qml.transforms.core.TransformContainer(mock_user_transform) - user_tp = qml.transforms.core.TransformProgram((container,)) - full_tp, _ = _setup_transform_program(user_tp, device, config) + full_tp, _ = _setup_transform_program(device, config) assert repr(full_tp) == "TransformProgram(mock_user_transform, _expand_transform_param_shift)" @@ -67,15 +65,14 @@ def test_device_transform_program(): device = qml.device("default.qubit") device.preprocess_transforms = MagicMock(return_value=device_tp) - user_transform_program = TransformProgram() - full_tp, inner_tp = _setup_transform_program(user_transform_program, device, config) + full_tp, inner_tp = _setup_transform_program(device, config) assert repr(full_tp) == "TransformProgram(device_transform)" assert inner_tp.is_empty() config.use_device_gradient = False - full_tp, inner_tp = _setup_transform_program(user_transform_program, device, config) + full_tp, inner_tp = _setup_transform_program(device, config) assert full_tp.is_empty() assert repr(inner_tp) == "TransformProgram(device_transform)" @@ -135,7 +132,7 @@ def test_prune_dynamic_transform_warning_raised(): config = ExecutionConfig(mcm_config=MCMConfig(mcm_method="one-shot")) with pytest.warns(UserWarning, match="A dynamic_one_shot transform already exists"): - _, __ = _setup_transform_program(user_transform_program, device, config) + _, __ = _setup_transform_program(device, config) def test_interface_data_not_supported(): @@ -144,7 +141,7 @@ def test_interface_data_not_supported(): device = qml.device("default.qubit") user_transform_program = TransformProgram() - full_tp, inner_tp = _setup_transform_program(user_transform_program, device, config) + full_tp, inner_tp = _setup_transform_program(device, config) assert full_tp.is_empty() assert qml.transforms.convert_to_numpy_parameters in inner_tp @@ -157,7 +154,7 @@ def test_interface_data_supported(): device = qml.device("default.mixed", wires=1) user_transform_program = TransformProgram() - _, inner_tp = _setup_transform_program(user_transform_program, device, config) + _, inner_tp = _setup_transform_program(device, config) assert qml.transforms.convert_to_numpy_parameters not in inner_tp @@ -166,7 +163,7 @@ def test_interface_data_supported(): device = qml.device("default.qubit") user_transform_program = TransformProgram() - _, inner_tp = _setup_transform_program(user_transform_program, device, config) + _, inner_tp = _setup_transform_program(device, config) assert qml.transforms.convert_to_numpy_parameters not in inner_tp @@ -175,7 +172,7 @@ def test_interface_data_supported(): device = qml.device("default.qubit") user_transform_program = TransformProgram() - _, inner_tp = _setup_transform_program(user_transform_program, device, config) + _, inner_tp = _setup_transform_program(device, config) assert qml.transforms.convert_to_numpy_parameters not in inner_tp @@ -194,13 +191,13 @@ def test_cache_handling(): device.preprocess_transforms = MagicMock(return_value=TransformProgram()) user_transform_program = TransformProgram() - full_tp, inner_tp = _setup_transform_program(user_transform_program, device, config, cache=True) + full_tp, inner_tp = _setup_transform_program(device, config, cache=True) assert repr(inner_tp) == "TransformProgram(_cache_transform)" assert full_tp.is_empty() full_tp, inner_tp = _setup_transform_program( - user_transform_program, device, config, cache=False + device, config, cache=False ) assert full_tp.is_empty() From 79a15d8d8132ad179ddc87918ca13cf1b38f9ec8 Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Wed, 7 May 2025 09:50:42 -0400 Subject: [PATCH 38/42] fmt --- pennylane/workflow/execution.py | 4 +--- tests/workflow/test_setup_transform_program.py | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/pennylane/workflow/execution.py b/pennylane/workflow/execution.py index c26db03d47f..feb25c0f8f7 100644 --- a/pennylane/workflow/execution.py +++ b/pennylane/workflow/execution.py @@ -211,9 +211,7 @@ def cost_fn(params, x): ) config = _resolve_execution_config(config, device, tapes) - outer_transform, inner_transform = _setup_transform_program( - device, config, cache, cachesize - ) + outer_transform, inner_transform = _setup_transform_program(device, config, cache, cachesize) #### Executing the configured setup ##### tapes, outer_post_processing = outer_transform(tapes) diff --git a/tests/workflow/test_setup_transform_program.py b/tests/workflow/test_setup_transform_program.py index 827b0bbd2c9..497bb81a795 100644 --- a/tests/workflow/test_setup_transform_program.py +++ b/tests/workflow/test_setup_transform_program.py @@ -196,9 +196,7 @@ def test_cache_handling(): assert repr(inner_tp) == "TransformProgram(_cache_transform)" assert full_tp.is_empty() - full_tp, inner_tp = _setup_transform_program( - device, config, cache=False - ) + full_tp, inner_tp = _setup_transform_program(device, config, cache=False) assert full_tp.is_empty() assert inner_tp.is_empty() From e0ac9c51c7141470717709d56472f1fbaf72e5bc Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Wed, 7 May 2025 10:21:17 -0400 Subject: [PATCH 39/42] adjusted one. fixed one. --- tests/workflow/test_setup_transform_program.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/workflow/test_setup_transform_program.py b/tests/workflow/test_setup_transform_program.py index 497bb81a795..887edab3780 100644 --- a/tests/workflow/test_setup_transform_program.py +++ b/tests/workflow/test_setup_transform_program.py @@ -52,7 +52,7 @@ def test_gradient_expand_transform(): full_tp, _ = _setup_transform_program(device, config) - assert repr(full_tp) == "TransformProgram(mock_user_transform, _expand_transform_param_shift)" + assert repr(full_tp) == "TransformProgram(_expand_transform_param_shift)" def test_device_transform_program(): @@ -180,7 +180,7 @@ def test_interface_data_supported(): convert_to_numpy=False, interface="jax", gradient_method=qml.gradients.param_shift ) - _, inner_tp = _setup_transform_program(TransformProgram(), device, config) + _, inner_tp = _setup_transform_program(device, config) assert qml.transforms.convert_to_numpy_parameters not in inner_tp From 5528ea0695723515f15cd297be369311f43511ce Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Wed, 7 May 2025 10:25:54 -0400 Subject: [PATCH 40/42] rm unused import/tp --- tests/workflow/interfaces/run/test_autograd_run.py | 1 - tests/workflow/interfaces/run/test_jax_jit_run.py | 1 - tests/workflow/interfaces/run/test_jax_run.py | 1 - .../workflow/interfaces/run/test_tensorflow_autograph_run.py | 1 - tests/workflow/interfaces/run/test_tensorflow_run.py | 1 - tests/workflow/interfaces/run/test_torch_run.py | 1 - tests/workflow/test_setup_transform_program.py | 5 ----- 7 files changed, 11 deletions(-) diff --git a/tests/workflow/interfaces/run/test_autograd_run.py b/tests/workflow/interfaces/run/test_autograd_run.py index 23beb77b5ec..bf0e2922418 100644 --- a/tests/workflow/interfaces/run/test_autograd_run.py +++ b/tests/workflow/interfaces/run/test_autograd_run.py @@ -25,7 +25,6 @@ import pennylane as qml from pennylane import numpy as pnp -from pennylane.transforms.core import TransformProgram from pennylane.workflow import _resolve_execution_config, _setup_transform_program, run diff --git a/tests/workflow/interfaces/run/test_jax_jit_run.py b/tests/workflow/interfaces/run/test_jax_jit_run.py index d18630d591a..a77c8b3a1af 100644 --- a/tests/workflow/interfaces/run/test_jax_jit_run.py +++ b/tests/workflow/interfaces/run/test_jax_jit_run.py @@ -23,7 +23,6 @@ from conftest import atol_for_shots, get_device, test_matrix import pennylane as qml -from pennylane.transforms.core import TransformProgram from pennylane.workflow import _resolve_execution_config, _setup_transform_program, run jax = pytest.importorskip("jax") diff --git a/tests/workflow/interfaces/run/test_jax_run.py b/tests/workflow/interfaces/run/test_jax_run.py index 516bfbea52f..6e8aec9d350 100644 --- a/tests/workflow/interfaces/run/test_jax_run.py +++ b/tests/workflow/interfaces/run/test_jax_run.py @@ -23,7 +23,6 @@ from conftest import atol_for_shots, get_device, test_matrix import pennylane as qml -from pennylane.transforms.core import TransformProgram from pennylane.workflow import _resolve_execution_config, _setup_transform_program, run jax = pytest.importorskip("jax") diff --git a/tests/workflow/interfaces/run/test_tensorflow_autograph_run.py b/tests/workflow/interfaces/run/test_tensorflow_autograph_run.py index f8a88dd53f6..070bb0ed961 100644 --- a/tests/workflow/interfaces/run/test_tensorflow_autograph_run.py +++ b/tests/workflow/interfaces/run/test_tensorflow_autograph_run.py @@ -24,7 +24,6 @@ import pennylane as qml from pennylane.tape import QuantumScript -from pennylane.transforms.core import TransformProgram from pennylane.workflow import _resolve_execution_config, _setup_transform_program, run tf = pytest.importorskip("tensorflow") diff --git a/tests/workflow/interfaces/run/test_tensorflow_run.py b/tests/workflow/interfaces/run/test_tensorflow_run.py index 01ba55a39f2..69435823857 100644 --- a/tests/workflow/interfaces/run/test_tensorflow_run.py +++ b/tests/workflow/interfaces/run/test_tensorflow_run.py @@ -24,7 +24,6 @@ import pennylane as qml from pennylane.tape import QuantumScript -from pennylane.transforms.core import TransformProgram from pennylane.workflow import _resolve_execution_config, _setup_transform_program, run tf = pytest.importorskip("tensorflow") diff --git a/tests/workflow/interfaces/run/test_torch_run.py b/tests/workflow/interfaces/run/test_torch_run.py index 4ea7c1fa9b4..919f7120be9 100644 --- a/tests/workflow/interfaces/run/test_torch_run.py +++ b/tests/workflow/interfaces/run/test_torch_run.py @@ -22,7 +22,6 @@ from conftest import atol_for_shots, get_device, test_matrix import pennylane as qml -from pennylane.transforms.core import TransformProgram from pennylane.workflow import _resolve_execution_config, _setup_transform_program, run torch = pytest.importorskip("torch") diff --git a/tests/workflow/test_setup_transform_program.py b/tests/workflow/test_setup_transform_program.py index 887edab3780..da9a529a721 100644 --- a/tests/workflow/test_setup_transform_program.py +++ b/tests/workflow/test_setup_transform_program.py @@ -140,7 +140,6 @@ def test_interface_data_not_supported(): config = ExecutionConfig(interface="autograd", gradient_method="adjoint") device = qml.device("default.qubit") - user_transform_program = TransformProgram() full_tp, inner_tp = _setup_transform_program(device, config) assert full_tp.is_empty() @@ -153,7 +152,6 @@ def test_interface_data_supported(): device = qml.device("default.mixed", wires=1) - user_transform_program = TransformProgram() _, inner_tp = _setup_transform_program(device, config) assert qml.transforms.convert_to_numpy_parameters not in inner_tp @@ -162,7 +160,6 @@ def test_interface_data_supported(): device = qml.device("default.qubit") - user_transform_program = TransformProgram() _, inner_tp = _setup_transform_program(device, config) assert qml.transforms.convert_to_numpy_parameters not in inner_tp @@ -171,7 +168,6 @@ def test_interface_data_supported(): device = qml.device("default.qubit") - user_transform_program = TransformProgram() _, inner_tp = _setup_transform_program(device, config) assert qml.transforms.convert_to_numpy_parameters not in inner_tp @@ -190,7 +186,6 @@ def test_cache_handling(): device = qml.device("default.qubit") device.preprocess_transforms = MagicMock(return_value=TransformProgram()) - user_transform_program = TransformProgram() full_tp, inner_tp = _setup_transform_program(device, config, cache=True) assert repr(inner_tp) == "TransformProgram(_cache_transform)" From 138cf67801ae531ca7dcf8d10633d2b89f9f7a40 Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Wed, 7 May 2025 14:04:28 -0400 Subject: [PATCH 41/42] the decoupling made this warning scheme redundant. removed therefore --- pennylane/workflow/_setup_transform_program.py | 11 ----------- tests/workflow/test_setup_transform_program.py | 12 ------------ 2 files changed, 23 deletions(-) diff --git a/pennylane/workflow/_setup_transform_program.py b/pennylane/workflow/_setup_transform_program.py index c33f0087d57..9b92ef64365 100644 --- a/pennylane/workflow/_setup_transform_program.py +++ b/pennylane/workflow/_setup_transform_program.py @@ -13,7 +13,6 @@ # limitations under the License. """Contains a function for setting up the inner and outer transform programs for execution of a QNode.""" -import warnings from cachetools import LRUCache @@ -49,17 +48,7 @@ def _prune_dynamic_transform(outer_transform, inner_transform): inner_contains_one_shot = inner_transform.prune_dynamic_transform(type_to_keep) if inner_contains_one_shot: type_to_keep = 0 - original_len = len(outer_transform) outer_transform.prune_dynamic_transform(type_to_keep) - outer_contained_one_shot = len(outer_transform) < original_len - if inner_contains_one_shot and outer_contained_one_shot: - warnings.warn( - "A dynamic_one_shot transform already exists in the preprocessing program of the " - "device. Therefore, the dynamic_one_shot applied on the qnode will be ignored. " - "See https://docs.pennylane.ai/en/stable/code/api/pennylane.dynamic_one_shot.html " - "for more information on the recommended way to use dynamic_one_shot.", - UserWarning, - ) def _setup_transform_program( diff --git a/tests/workflow/test_setup_transform_program.py b/tests/workflow/test_setup_transform_program.py index da9a529a721..9b641b88683 100644 --- a/tests/workflow/test_setup_transform_program.py +++ b/tests/workflow/test_setup_transform_program.py @@ -123,18 +123,6 @@ def test_prune_dynamic_transform_with_mcm(): assert len(program2) == 1 -def test_prune_dynamic_transform_warning_raised(): - """Tests that a warning raised when a user-applied dynamic-one-shot transform is ignored.""" - - user_transform_program = TransformProgram() - user_transform_program.add_transform(qml.transforms.dynamic_one_shot) - device = qml.device("default.qubit") - config = ExecutionConfig(mcm_config=MCMConfig(mcm_method="one-shot")) - - with pytest.warns(UserWarning, match="A dynamic_one_shot transform already exists"): - _, __ = _setup_transform_program(device, config) - - def test_interface_data_not_supported(): """Test that convert_to_numpy_parameters transform is correctly added.""" config = ExecutionConfig(interface="autograd", gradient_method="adjoint") From 95d4a38873c057012948dce246e0fec82066abd7 Mon Sep 17 00:00:00 2001 From: JerryChen97 Date: Wed, 7 May 2025 14:12:45 -0400 Subject: [PATCH 42/42] rm unused --- tests/workflow/test_setup_transform_program.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/workflow/test_setup_transform_program.py b/tests/workflow/test_setup_transform_program.py index 9b641b88683..c03a7749c0d 100644 --- a/tests/workflow/test_setup_transform_program.py +++ b/tests/workflow/test_setup_transform_program.py @@ -15,10 +15,8 @@ from unittest.mock import MagicMock -import pytest - import pennylane as qml -from pennylane.devices import ExecutionConfig, MCMConfig +from pennylane.devices import ExecutionConfig from pennylane.transforms.core import TransformProgram from pennylane.workflow._setup_transform_program import ( _prune_dynamic_transform,