class_docstr: Default qubit device for PennyLane.
  
  .. warning::
  
      This is the legacy implementation of DefaultQubit. It has been replaced by
      ``qml.devices.DefaultQubit``, which can be accessed with the familiar constructor,
      ``qml.device("default.qubit")``.
  
      This change will not alter device behaviour for most workflows, but may have implications for
      plugin developers and users who directly interact with device methods. Please consult
      :class:`pennylane.devices.Device` and the implementation in
      :class:`pennylane.devices.DefaultQubit` for more information on what the new
      interface will look like and be prepared to make updates in a coming release. If you have any
      feedback on these changes, please create an
      `issue <https://github.com/PennyLaneAI/pennylane/issues>`_ or post in our
      `discussion forum <https://discuss.pennylane.ai/>`_.
  
  Args:
      wires (int, Iterable[Number, str]): Number of subsystems represented by the device,
          or iterable that contains unique labels for the subsystems as numbers (i.e., ``[-1, 0, 2]``)
          or strings (``['ancilla', 'q1', 'q2']``). Default 1 if not specified.
      shots (None, int): How many times the circuit should be evaluated (or sampled) to estimate
          the expectation values. Defaults to ``None`` if not specified, which means that the device
          returns analytical results.
class_docstr_tok: ["Default","qubit","device","for","PennyLane",".","..","warning",":",":","This","is","the","legacy","implementation","of","DefaultQubit",".","It","has","been","replaced","by","``","qml.devices.DefaultQubit","``",",","which","can","be","accessed","with","the","familiar","constructor",",","``","qml.device","(","``","default.qubit","''",")","``",".","This","change","will","not","alter","device","behaviour","for","most","workflows",",","but","may","have","implications","for","plugin","developers","and","users","who","directly","interact","with","device","methods",".","Please","consult",":","class",":","`","pennylane.devices.Device","`","and","the","implementation","in",":","class",":","`","pennylane.devices.DefaultQubit","`","for","more","information","on","what","the","new","interface","will","look","like","and","be","prepared","to","make","updates","in","a","coming","release",".","If","you","have","any","feedback","on","these","changes",",","please","create","an","`","issue","<","https",":","\/\/github.com\/PennyLaneAI\/pennylane\/issues",">","`","_","or","post","in","our","`","discussion","forum","<","https",":","\/\/discuss.pennylane.ai\/",">","`","_",".","Args",":","wires","(","int",",","Iterable","[","Number",",","str","]",")",":","Number","of","subsystems","represented","by","the","device",",","or","iterable","that","contains","unique","labels","for","the","subsystems","as","numbers","(","i.e.",",","``","[","-1",",","0",",","2","]","``",")","or","strings","(","``","[","'ancilla","'",",","'q1","'",",","'q2","'","]","``",")",".","Default","1","if","not","specified",".","shots","(","None",",","int",")",":","How","many","times","the","circuit","should","be","evaluated","(","or","sampled",")","to","estimate","the","expectation","values",".","Defaults","to","``","None","``","if","not","specified",",","which","means","that","the","device","returns","analytical","results","."]
docstr: Returns the measured bits and recipes in the classical shadow protocol.
  
  The protocol is described in detail in the `classical shadows paper <https://arxiv.org/abs/2002.08953>`_.
  This measurement process returns the randomized Pauli measurements (the ``recipes``)
  that are performed for each qubit and snapshot as an integer:
  
  - 0 for Pauli X,
  - 1 for Pauli Y, and
  - 2 for Pauli Z.
  
  It also returns the measurement results (the ``bits``); 0 if the 1 eigenvalue
  is sampled, and 1 if the -1 eigenvalue is sampled.
  
  The device shots are used to specify the number of snapshots. If ``T`` is the number
  of shots and ``n`` is the number of qubits, then both the measured bits and the
  Pauli measurements have shape ``(T, n)``.
  
  This implementation leverages vectorization and offers a significant speed-up over
  the generic implementation.
  
  .. Note::
  
      This method internally calls ``np.einsum`` which supports at most 52 indices,
      thus the classical shadow measurement for this device supports at most 52
      qubits.
  
  .. seealso:: :func:`~pennylane.classical_shadow`
  
  Args:
      obs (~.pennylane.measurements.ClassicalShadowMP): The classical shadow measurement process
      circuit (~.tape.QuantumTape): The quantum tape that is being executed
  
  Returns:
      tensor_like[int]: A tensor with shape ``(2, T, n)``, where the first row represents
      the measured bits and the second represents the recipes used.
code: def classical_shadow(self, obs, circuit):
      """
      Returns the measured bits and recipes in the classical shadow protocol.
  
      The protocol is described in detail in the `classical shadows paper <https://arxiv.org/abs/2002.08953>`_.
      This measurement process returns the randomized Pauli measurements (the ``recipes``)
      that are performed for each qubit and snapshot as an integer:
  
      - 0 for Pauli X,
      - 1 for Pauli Y, and
      - 2 for Pauli Z.
  
      It also returns the measurement results (the ``bits``); 0 if the 1 eigenvalue
      is sampled, and 1 if the -1 eigenvalue is sampled.
  
      The device shots are used to specify the number of snapshots. If ``T`` is the number
      of shots and ``n`` is the number of qubits, then both the measured bits and the
      Pauli measurements have shape ``(T, n)``.
  
      This implementation leverages vectorization and offers a significant speed-up over
      the generic implementation.
  
      .. Note::
  
          This method internally calls ``np.einsum`` which supports at most 52 indices,
          thus the classical shadow measurement for this device supports at most 52
          qubits.
  
      .. seealso:: :func:`~pennylane.classical_shadow`
  
      Args:
          obs (~.pennylane.measurements.ClassicalShadowMP): The classical shadow measurement process
          circuit (~.tape.QuantumTape): The quantum tape that is being executed
  
      Returns:
          tensor_like[int]: A tensor with shape ``(2, T, n)``, where the first row represents
          the measured bits and the second represents the recipes used.
      """
      wires = obs.wires
      seed = obs.seed
  
      n_qubits = len(wires)
      n_snapshots = self.shots
      device_qubits = len(self.wires)
      mapped_wires = np.array(self.map_wires(wires))
  
      # seed the random measurement generation so that recipes
      # are the same for different executions with the same seed
      rng = np.random.RandomState(seed)
      recipes = rng.randint(0, 3, size=(n_snapshots, n_qubits))
  
      obs_list = self._stack(
          [
              qml.PauliX.compute_matrix(),
              qml.PauliY.compute_matrix(),
              qml.PauliZ.compute_matrix(),
          ]
      )
      uni_list = self._stack(
          [
              qml.Hadamard.compute_matrix(),
              qml.Hadamard.compute_matrix()
              @ qml.RZ.compute_matrix(-np.pi / 2),
              qml.Identity.compute_matrix(),
          ]
      )
      obs = obs_list[recipes]
      uni = uni_list[recipes]
  
      # There's a significant speedup if we use the following iterative
      # process to perform the randomized Pauli measurements:
      #   1. Randomly generate Pauli observables for all snapshots for
      #      a single qubit (e.g. the first qubit).
      #   2. Compute the expectation of each Pauli observable on the first
      #      qubit by tracing out all other qubits.
      #   3. Sample the first qubit based on each Pauli expectation.
      #   4. For all snapshots, determine the collapsed state of the remaining
      #      qubits based on the sample result.
      #   4. Repeat iteratively until no qubits are remaining.
      #
      # Observe that after the first iteration, the second qubit will become the
      # "first" qubit in the process. The advantage to this approach as opposed to
      # simulataneously computing the Pauli expectations for each qubit is that
      # the partial traces are computed over iteratively smaller subsystems, leading
      # to a significant speed-up.
  
      # transpose the state so that the measured wires appear first
      unmeasured_wires = [
          i for i in range(len(self.wires)) if i not in mapped_wires
      ]
      transposed_state = np.transpose(
          self._state, axes=mapped_wires.tolist() + unmeasured_wires
      )
  
      outcomes = np.zeros((n_snapshots, n_qubits))
      stacked_state = self._stack(
          [transposed_state for _ in range(n_snapshots)]
      )
  
      for i in range(n_qubits):
          # trace out every qubit except the first
          first_qubit_state = self._einsum(
              f"{ABC[device_qubits - i + 1]}{ABC[:device_qubits - i]},{ABC[device_qubits - i + 1]}{ABC[device_qubits - i]}{ABC[1:device_qubits - i]}"
              f"->{ABC[device_qubits - i + 1]}a{ABC[device_qubits - i]}",
              stacked_state,
              self._conj(stacked_state),
          )
  
          # sample the observables on the first qubit
          probs = (
              self._einsum("abc,acb->a", first_qubit_state, obs[:, i])
              + 1
          ) / 2
          samples = np.random.uniform(0, 1, size=probs.shape) > probs
          outcomes[:, i] = samples
  
          # collapse the state of the remaining qubits; the next qubit in line
          # becomes the first qubit for the next iteration
          rotated_state = self._einsum(
              "ab...,acb->ac...", stacked_state, uni[:, i]
          )
          stacked_state = rotated_state[
              np.arange(n_snapshots), self._cast(samples, np.int8)
          ]
  
          # re-normalize the collapsed state
          norms = np.sqrt(
              np.sum(
                  np.abs(stacked_state) ** 2,
                  tuple(range(1, device_qubits - i)),
                  keepdims=True,
              )
          )
          stacked_state /= norms
  
      return self._cast(self._stack([outcomes, recipes]), dtype=np.int8)
  
imports: import functools
  import itertools
  from string import ascii_letters
  from typing import List
  import numpy
  from scipy.sparse import csr_matrix
  import pennylane
  from pennylane import BasisState, DeviceError, QubitDevice, StatePrep, Snapshot
  from pennylane.devices.qubit import measure
  from pennylane.operation import Operation
  from pennylane.ops import Sum
  from pennylane.ops.qubit.attributes import diagonal_in_z_basis
  from pennylane.pulse import ParametrizedEvolution
  from pennylane.measurements import ExpectationMP
  from pennylane.typing import TensorLike
  from pennylane.wires import WireError
  from .._version import __version__
label_desc: Use image node_id 34 for calling the DefaultQubitLegacy obj's underlying member method code with example usage: obj.classical_shadow(obs, circuit) and returns: self