class_docstr: An operation representing the QDrift approximation for the complex matrix exponential
  of a given Hamiltonian.
  
  The QDrift subroutine provides a method to approximate the matrix exponential of a Hamiltonian
  expressed as a linear combination of terms which in general do not commute. For the Hamiltonian
  :math:`H = \Sigma_j h_j H_{j}`, the product formula is constructed by random sampling from the
  terms of the Hamiltonian with the probability :math:`p_j = h_j / \sum_{j} hj` as:
  
  .. math::
  
      \prod_{j}^{n} e^{i \lambda H_j \tau / n},
  
  where :math:`\tau` is time, :math:`\lambda = \sum_j |h_j|` and :math:`n` is the total number of
  terms to be sampled and added to the product. Note, the terms :math:`H_{j}` are assumed to be
  normalized such that the "impact" of each term is fully encoded in the magnitude of :math:`h_{j}`.
  
  The number of samples :math:`n` required for a given error threshold can be approximated by:
  
  .. math::
  
      n \ \approx \ \frac{2\lambda^{2}t^{2}}{\epsilon}
  
  For more details see `Phys. Rev. Lett. 123, 070503 (2019) <https://arxiv.org/abs/1811.08017>`_.
  
  Args:
      hamiltonian (Union[.Hamiltonian, .Sum]): The Hamiltonian written as a sum of operations
      time (float): The time of evolution, namely the parameter :math:`t` in :math:`e^{iHt}`
      n (int): An integer representing the number of exponentiated terms
      seed (int): The seed for the random number generator
  
  Raises:
      TypeError: The ``hamiltonian`` is not of type :class:`~.Hamiltonian`, or :class:`~.Sum`
      QuantumFunctionError: If the coefficients of ``hamiltonian`` are trainable and are used
          in a differentiable workflow.
  
  **Example**
  
  .. code-block:: python3
  
      coeffs = [0.25, 0.75]
      ops = [qml.PauliX(0), qml.PauliZ(0)]
      H = qml.dot(coeffs, ops)
  
      dev = qml.device("default.qubit", wires=2)
      @qml.qnode(dev)
      def my_circ():
          # Prepare some state
          qml.Hadamard(0)
  
          # Evolve according to H
          qml.QDrift(H, time=1.2, n=10, seed=10)
  
          # Measure some quantity
          return qml.probs()
  
  >>> my_circ()
  array([0.65379493, 0.        , 0.34620507, 0.        ])
  
  
  .. details::
      :title: Usage Details
  
      We currently **Do NOT** support computing gradients with respect to the
      coefficients of the input Hamiltonian. We can however compute the gradient
      with respect to the evolution time:
  
      .. code-block:: python3
  
          dev = qml.device("default.qubit", wires=2)
  
          @qml.qnode(dev)
          def my_circ(time):
              # Prepare H:
              H = qml.dot([0.2, -0.1], [qml.PauliY(0), qml.PauliZ(1)])
  
              # Prepare some state
              qml.Hadamard(0)
  
              # Evolve according to H
              qml.QDrift(H, time, n=10, seed=10)
  
              # Measure some quantity
              return qml.expval(qml.PauliZ(0) @ qml.PauliZ(1))
  
  
      >>> time = np.array(1.23)
      >>> print(qml.grad(my_circ)(time))
      0.27980654844422853
  
      The error in the approximation of time evolution with the QDrift protocol is
      directly related to the number of samples used in the product. We provide a
      method to upper-bound the error:
  
      >>> H = qml.dot([0.25, 0.75], [qml.PauliX(0), qml.PauliZ(0)])
      >>> print(qml.QDrift.error(H, time=1.2, n=10))
      0.3661197552925645
docstr: Recreate an operation from its serialized format.
  
  Args:
      data: the trainable component of the operation
      metadata: the non-trainable component of the operation
  
  The output of ``Operator._flatten`` and the class type must be sufficient to reconstruct the original
  operation with ``Operator._unflatten``.
  
  **Example:**
  
  >>> op = qml.Rot(1.2, 2.3, 3.4, wires=0)
  >>> op._flatten()
  ((1.2, 2.3, 3.4), (<Wires = [0]>, ()))
  >>> qml.Rot._unflatten(*op._flatten())
  >>> op = qml.PauliRot(1.2, "XY", wires=(0,1))
  >>> op._flatten()
  ((1.2,), (<Wires = [0, 1]>, (('pauli_word', 'XY'),)))
  >>> op = qml.ctrl(qml.U2(3.4, 4.5, wires="a"), ("b", "c") )
  >>> type(op)._unflatten(*op._flatten())
  Controlled(U2(3.4, 4.5, wires=['a']), control_wires=['b', 'c'])
docstr_tok: ["Recreate","an","operation","from","its","serialized","format",".","Args",":","data",":","the","trainable","component","of","the","operation","metadata",":","the","non-trainable","component","of","the","operation","The","output","of","``","Operator._flatten","``","and","the","class","type","must","be","sufficient","to","reconstruct","the","original","operation","with","``","Operator._unflatten","``",".","*","*","Example",":","*","*",">",">",">","op","=","qml.Rot","(","1.2",",","2.3",",","3.4",",","wires=0",")",">",">",">","op._flatten","(",")","(","(","1.2",",","2.3",",","3.4",")",",","(","<","Wires","=","[","0","]",">",",","(",")",")",")",">",">",">","qml.Rot._unflatten","(","*","op._flatten","(",")",")",">",">",">","op","=","qml.PauliRot","(","1.2",",","``","XY","''",",","wires=","(","0,1",")",")",">",">",">","op._flatten","(",")","(","(","1.2",",",")",",","(","<","Wires","=","[","0",",","1","]",">",",","(","(","'pauli_word","'",",","'XY","'",")",",",")",")",")",">",">",">","op","=","qml.ctrl","(","qml.U2","(","3.4",",","4.5",",","wires=","''","a","''",")",",","(","``","b","''",",","``","c","''",")",")",">",">",">","type","(","op",")","._unflatten","(","*","op._flatten","(",")",")","Controlled","(","U2","(","3.4",",","4.5",",","wires=","[","'","a","'","]",")",",","control_wires=","[","'","b","'",",","'","c","'","]",")"]
code: def _unflatten(cls, data, metadata):
      """Recreate an operation from its serialized format.
  
      Args:
          data: the trainable component of the operation
          metadata: the non-trainable component of the operation
  
      The output of ``Operator._flatten`` and the class type must be sufficient to reconstruct the original
      operation with ``Operator._unflatten``.
  
      **Example:**
  
      >>> op = qml.Rot(1.2, 2.3, 3.4, wires=0)
      >>> op._flatten()
      ((1.2, 2.3, 3.4), (<Wires = [0]>, ()))
      >>> qml.Rot._unflatten(*op._flatten())
      >>> op = qml.PauliRot(1.2, "XY", wires=(0,1))
      >>> op._flatten()
      ((1.2,), (<Wires = [0, 1]>, (('pauli_word', 'XY'),)))
      >>> op = qml.ctrl(qml.U2(3.4, 4.5, wires="a"), ("b", "c") )
      >>> type(op)._unflatten(*op._flatten())
      Controlled(U2(3.4, 4.5, wires=['a']), control_wires=['b', 'c'])
  
      """
      hyperparameters_dict = dict(metadata[1])
      hamiltonian = hyperparameters_dict.pop("base")
      return cls(hamiltonian, *data, **hyperparameters_dict)
  
file_path: pennylane/pennylane/templates/subroutines/qdrift.py
imports: import pennylane
  from pennylane.operation import Operation
  from pennylane.math import requires_grad, unwrap
  from pennylane.ops import Sum, SProd, Hamiltonian
label_desc: Use image node_id 2 for calling the QDrift obj's underlying member method code with example usage: obj._unflatten(cls, data, metadata) and returns: cls