Skip to content

Error in classical_shadow as return type when using program sets on QPU #313

@BenchenH

Description

@BenchenH

Describe the bug
An error is encountered when using program sets (implicitly invoked) on QPU with the qml.classical_shadow(wires) as return type.

To reproduce

import pennylane as qml
from pennylane import numpy as np
from functools import partial

dev = qml.device(
    "braket.aws.qubit",
    device_arn="arn:aws:braket:us-west-1::device/qpu/rigetti/Ankaa-3",
    wires=2,
)

@partial(qml.set_shots, shots=10)
@qml.qnode(dev)
def bell_circuit():
    qml.Hadamard(0)
    qml.CNOT((0,1))
    return qml.classical_shadow(wires=range(2))

bits, recipes = bell_circuit()

Expected behavior
When dev = qml.device("default.qubit", wires=2) is set as the backend, the above code could run successfully without any error. One would expect the above code to run normally on a real QPU.

Screenshots or logs

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[7], line 16
     13     qml.CNOT((0, 1))
     14     return qml.classical_shadow(wires=range(2))
---> 16 bits, recipes = bell_circuit()

File ~/anaconda3/envs/Braket/lib/python3.10/site-packages/pennylane/workflow/qnode.py:922, in QNode.__call__(self, *args, **kwargs)
    919     from ._capture_qnode import capture_qnode  # pylint: disable=import-outside-toplevel
    921     return capture_qnode(self, *args, **kwargs)
--> 922 return self._impl_call(*args, **kwargs)

File ~/anaconda3/envs/Braket/lib/python3.10/site-packages/pennylane/workflow/qnode.py:895, in QNode._impl_call(self, *args, **kwargs)
    892 # Calculate the classical jacobians if necessary
    893 self._transform_program.set_classical_component(self, args, kwargs)
--> 895 res = execute(
    896     (tape,),
    897     device=self.device,
    898     diff_method=self.diff_method,
    899     interface=self.interface,
    900     transform_program=self._transform_program,
    901     gradient_kwargs=self.gradient_kwargs,
    902     **self.execute_kwargs,
    903 )
    904 res = res[0]
    906 # convert result to the interface in case the qfunc has no parameters

File ~/anaconda3/envs/Braket/lib/python3.10/site-packages/pennylane/workflow/execution.py:233, in execute(tapes, device, diff_method, interface, grad_on_execution, cache, cachesize, max_diff, device_vjp, postselect_mode, mcm_method, gradient_kwargs, transform_program, executor_backend)
    229 tapes, outer_post_processing = outer_transform(tapes)
    231 assert not outer_transform.is_informative, "should only contain device preprocessing"
--> 233 results = run(tapes, device, config, inner_transform)
    234 return user_post_processing(outer_post_processing(results))

File ~/anaconda3/envs/Braket/lib/python3.10/site-packages/pennylane/workflow/run.py:291, in run(tapes, device, config, inner_transform_program)
    287 no_interface_boundary_required = (
    288     config.interface == Interface.NUMPY or config.gradient_method == "backprop"
    289 )
    290 if no_interface_boundary_required:
--> 291     results = inner_execute(tapes)
    292     return results
    294 # TODO: Prune once support for tf-autograph is dropped

File ~/anaconda3/envs/Braket/lib/python3.10/site-packages/pennylane/workflow/run.py:256, in _make_inner_execute.<locals>.inner_execute(tapes)
    253 transformed_tapes, transform_post_processing = inner_transform(tapes)
    255 if transformed_tapes:
--> 256     results = device.execute(transformed_tapes, execution_config=execution_config)
    257 else:
    258     results = ()

File ~/anaconda3/envs/Braket/lib/python3.10/site-packages/pennylane/devices/modifiers/single_tape_support.py:30, in _make_execute.<locals>.execute(self, circuits, execution_config)
     28     is_single_circuit = True
     29     circuits = (circuits,)
---> 30 results = batch_execute(self, circuits, execution_config)
     31 return results[0] if is_single_circuit else results

File ~/anaconda3/envs/Braket/lib/python3.10/site-packages/pennylane/devices/legacy_facade.py:378, in LegacyDeviceFacade.execute(self, circuits, execution_config)
    376 first_shot = circuits[0].shots
    377 if all(t.shots == first_shot for t in circuits):
--> 378     return _set_shots(dev, first_shot)(dev.batch_execute)(circuits, **kwargs)
    379 return tuple(
    380     _set_shots(dev, t.shots)(dev.batch_execute)((t,), **kwargs)[0] for t in circuits
    381 )

File ~/anaconda3/envs/Braket/lib/python3.10/contextlib.py:79, in ContextDecorator.__call__.<locals>.inner(*args, **kwds)
     76 @wraps(func)
     77 def inner(*args, **kwds):
     78     with self._recreate_cm():
---> 79         return func(*args, **kwds)

File ~/anaconda3/envs/Braket/lib/python3.10/site-packages/braket/pennylane_plugin/braket_device.py:240, in BraketQubitDevice.batch_execute(self, circuits, **run_kwargs)
    232 batch_shots = 0 if self.analytic else self.shots
    234 batch_inputs = (
    235     [{f"p_{k}": v for k, v in trainable.items()} for trainable in all_trainable]
    236     if self._parametrize_differentiable
    237     else []
    238 )
--> 240 return self._run_task_batch(braket_circuits, circuits, batch_shots, batch_inputs)

File ~/anaconda3/envs/Braket/lib/python3.10/site-packages/braket/pennylane_plugin/braket_device.py:718, in BraketAwsQubitDevice._run_task_batch(self, braket_circuits, pl_circuits, batch_shots, inputs)
    705     program_set = (
    706         ProgramSet.zip(braket_circuits, input_sets=inputs)
    707         if inputs
    708         else ProgramSet(braket_circuits)
    709     )
    710     task = self._device.run(
    711         program_set,
    712         s3_destination_folder=self._s3_folder,
   (...)
    716         **self._run_kwargs,
    717     )
--> 718     return self._braket_program_set_to_pl_result(task.result(), pl_circuits)
    719 task_batch = self._device.run_batch(
    720     braket_circuits,
    721     s3_destination_folder=self._s3_folder,
   (...)
    728     **self._run_kwargs,
    729 )
    731 # Call results() to retrieve the Braket results in parallel.

File ~/anaconda3/envs/Braket/lib/python3.10/site-packages/braket/pennylane_plugin/braket_device.py:409, in BraketQubitDevice._braket_program_set_to_pl_result(self, program_set_result, circuits)
    405     measurements = program_result[0].measurements
    407     # Program sets require shots > 0,
    408     # so the circuit's measurements are guaranteed to be SampleMeasurements
--> 409     executable_results = [
    410         measurement.process_samples(measurements, wire_order=measurement.wires)
    411         for measurement in circuit.measurements
    412     ]
    413     results.append(
    414         onp.array(executable_results).squeeze()
    415         if len(circuit.measurements) == 1
    416         else tuple(onp.array(result).squeeze() for result in executable_results)
    417     )
    418 return results

File ~/anaconda3/envs/Braket/lib/python3.10/site-packages/braket/pennylane_plugin/braket_device.py:410, in <listcomp>(.0)
    405     measurements = program_result[0].measurements
    407     # Program sets require shots > 0,
    408     # so the circuit's measurements are guaranteed to be SampleMeasurements
    409     executable_results = [
--> 410         measurement.process_samples(measurements, wire_order=measurement.wires)
    411         for measurement in circuit.measurements
    412     ]
    413     results.append(
    414         onp.array(executable_results).squeeze()
    415         if len(circuit.measurements) == 1
    416         else tuple(onp.array(result).squeeze() for result in executable_results)
    417     )
    418 return results

AttributeError: 'ClassicalShadowMP' object has no attribute 'process_samples'

System information
A description of your system. Please provide:

  • Amazon Braket Python PennyLane Plugin version: 1.33.4
  • Amazon Braket Python SDK version: 1.103.0
  • Amazon Braket Python Schemas version: 1.26.1
  • Amazon Braket Python Default Simulator version: 1.32.0
  • Python version: 3.10.19

Additional context
Add any other context about the problem here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions