class_docstr: Tests for the SPSA gradient transform
class_docstr_tok: ["Tests","for","the","SPSA","gradient","transform"]
docstr: Test differentiation of a QNode on a device supporting a
  special observable that returns an object rather than a number.
docstr_tok: ["Test","differentiation","of","a","QNode","on","a","device","supporting","a","special","observable","that","returns","an","object","rather","than","a","number","."]
code: def test_special_observable_qnode_differentiation(self):
      """Test differentiation of a QNode on a device supporting a
      special observable that returns an object rather than a number."""
  
      class SpecialObject:
          """SpecialObject
  
          A special object that conveniently encapsulates the return value of
          a special observable supported by a special device and which supports
          multiplication with scalars and addition.
          """
  
          def __init__(self, val):
              self.val = val
  
          def __mul__(self, other):
              return SpecialObject(self.val * other)
  
          def __rmul__(self, other):
              return self * other
  
          def __add__(self, other):
              new = self.val + (
                  other.val
                  if isinstance(other, self.__class__)
                  else other
              )
              return SpecialObject(new)
  
      class SpecialObservable(Observable):
          """SpecialObservable"""
  
          # pylint:disable=too-few-public-methods
  
          num_wires = AnyWires
  
          def diagonalizing_gates(self):
              """Diagonalizing gates"""
              return []
  
      class DeviceSupportingSpecialObservable(DefaultQubitLegacy):
          """A device class supporting SpecialObservable."""
  
          # pylint:disable=too-few-public-methods
          name = "Device supporting SpecialObservable"
          short_name = "default.qubit.specialobservable"
          observables = DefaultQubitLegacy.observables.union(
              {"SpecialObservable"}
          )
  
          @staticmethod
          def _asarray(arr, dtype=None):
              return np.array(arr, dtype=dtype)
  
          def __init__(self, *args, **kwargs):
              super().__init__(*args, **kwargs)
              self.R_DTYPE = SpecialObservable
  
          def expval(self, observable, **kwargs):
              """Compute the expectation value by returning a SpecialObject
              if the observable is a SpecialObservable and the device is analytic.
              """
              if self.analytic and isinstance(
                  observable, SpecialObservable
              ):
                  val = super().expval(qml.PauliZ(wires=0), **kwargs)
                  return SpecialObject(val)
  
              return super().expval(observable, **kwargs)
  
      dev = DeviceSupportingSpecialObservable(wires=1, shots=None)
  
      @qml.qnode(dev, diff_method="spsa")
      def qnode(x):
          qml.RY(x, wires=0)
          return qml.expval(SpecialObservable(wires=0))
  
      @qml.qnode(dev, diff_method="spsa")
      def reference_qnode(x):
          qml.RY(x, wires=0)
          return qml.expval(qml.PauliZ(wires=0))
  
      par = np.array(0.2, requires_grad=True)
      assert np.isclose(qnode(par).item().val, reference_qnode(par))
      assert np.isclose(
          qml.jacobian(qnode)(par).item().val,
          qml.jacobian(reference_qnode)(par),
      )
  
imports: import numpy
  import pytest
  import pennylane
  from pennylane import numpy
  from pennylane.devices import DefaultQubitLegacy
  from pennylane.gradients import spsa_grad
  from pennylane.gradients.spsa_gradient import _rademacher_sampler
  from pennylane.operation import AnyWires, Observable
label_desc: Use image node_id 18 for calling the TestSpsaGradient obj's underlying member method code with example usage: obj.test_special_observable_qnode_differentiation() and returns: qml, qml, SpecialObject, unknown, SpecialObject, list, np, super, SpecialObject