class_docstr: Riemannian gradient optimizer.
  
  Riemannian gradient descent algorithms can be used to optimize a function directly on a Lie group
  as opposed to on an Euclidean parameter space. Consider the function
  :math:`f(U) = \text{Tr}(U \rho_0 U^\dagger H)`
  for a given Hamiltonian :math:`H`, unitary :math:`U\in \text{SU}(2^N)` and initial state
  :math:`\rho_0`. One can show that this function is minimized by the flow equation
  
  .. math::
  
      \dot{U} = \text{grad}f(U)
  
  where :math:`\text{grad}` is the Riemannian gradient operator on :math:`\text{SU}(2^N)`.
  By discretizing the flow above, we see that a step of this optimizer
  iterates the Riemannian gradient flow on :math:`\text{SU}(2^N)` as
  
  .. math::
  
      U^{(t+1)} = \exp\left\{\epsilon\: \text{grad}f(U^{(t)}) U^{(t)}\right\},
  
  
  where :math:`\epsilon` is a user-defined hyperparameter corresponding to the step size.
  
  The Riemannian gradient in the Lie algebra is given by
  
  .. math::
  
      \text{grad}f(U^{(t)}) = -\left[U \rho U^\dagger, H\right] .
  
  
  Hence we see that subsequent steps of this optimizer will append the unitary generated by the Riemannian
  gradient and grow the circuit.
  
  The exact Riemannian gradient flow on :math:`\text{SU}(2^N)` has desirable optimization properties
  that can guarantee convergence to global minima under mild assumptions. However, this comes
  at a cost. Since :math:`\text{dim}(\text{SU}(2^N)) = 4^N-1`, we need an exponential number
  of parameters to calculate the gradient. This will not be problematic for small systems (:math:`N<5`),
  but will quickly get out of control as the number of qubits increases.
  
  To resolve this issue, we can restrict the Riemannian gradient to a subspace of the Lie algebra and calculate an
  approximate Riemannian gradient flow. The choice of restriction will affect the optimization behavior
  and quality of the final solution.
  
  For more information on Riemannian gradient flows on Lie groups see
  `T. Schulte-Herbrueggen et. al. (2008) <https://arxiv.org/abs/0802.4195>`_
  and the application to quantum circuits
  `Wiersema and Killoran (2022) <https://arxiv.org/abs/2202.06976>`_.
  
  Args:
      circuit (.QNode): a user defined circuit that does not take any arguments and returns
          the expectation value of a ``qml.Hamiltonian``.
      stepsize (float): the user-defined hyperparameter :math:`\epsilon`.
      restriction (.Hamiltonian): Restrict the Lie algebra to a corresponding subspace of
          the full Lie algebra. This restriction should be passed in the form of a
          ``qml.Hamiltonian`` that consists only of Pauli words.
      exact (bool): Flag that indicates wether we approximate the Riemannian gradient with a
          Trotterization or calculate the exact evolution via a matrix exponential. The latter is
          not hardware friendly and can only be done in simulation.
  
  **Examples**
  
  Define a Hamiltonian cost function to minimize:
  
  >>> coeffs = [-1., -1., -1.]
  >>> observables = [qml.PauliX(0), qml.PauliZ(1), qml.PauliY(0) @ qml.PauliX(1)]
  >>> hamiltonian = qml.Hamiltonian(coeffs, observables)
  
  Create an initial state and return the expectation value of the Hamiltonian:
  
  >>> @qml.qnode(qml.device("default.qubit", wires=2))
  ... def quant_fun():
  ...     qml.RX(0.1, wires=[0])
  ...     qml.RY(0.5, wires=[1])
  ...     qml.CNOT(wires=[0,1])
  ...     qml.RY(0.6, wires=[0])
  ...     return qml.expval(hamiltonian)
  
  Instantiate the optimizer with the initial circuit and the cost function and set the stepsize
  accordingly:
  
  >>> opt = qml.RiemannianGradientOptimizer(circuit=quant_fun, stepsize=0.1)
  
  Applying 5 steps gets us close the ground state of :math:`E\approx-2.23`:
  
  >>> for step in range(6):
  ...    circuit, cost = opt.step_and_cost()
  ...    print(f"Step {step} - cost {cost}")
  Step 0 - cost -1.3351865007304005
  Step 1 - cost -1.9937887238935206
  Step 2 - cost -2.1524234485729834
  Step 3 - cost -2.1955105378898487
  Step 4 - cost -2.2137628169764256
  Step 5 - cost -2.2234364822091575
  
  The optimized circuit is returned at each step, and can be used as any other QNode:
  
  >>> circuit()
  -2.2283086057521713
class_docstr_tok: ["Riemannian","gradient","optimizer",".","Riemannian","gradient","descent","algorithms","can","be","used","to","optimize","a","function","directly","on","a","Lie","group","as","opposed","to","on","an","Euclidean","parameter","space",".","Consider","the","function",":","math",":","`","f","(","U",")","=","\\text","{","Tr","}","(","U","\\rho_0","U^\\dagger","H",")","`","for","a","given","Hamiltonian",":","math",":","`","H","`",",","unitary",":","math",":","`","U\\in","\\text","{","SU","}","(","2^N",")","`","and","initial","state",":","math",":","`","\\rho_0","`",".","One","can","show","that","this","function","is","minimized","by","the","flow","equation","..","math",":",":","\\dot","{","U","}","=","\\text","{","grad","}","f","(","U",")","where",":","math",":","`","\\text","{","grad","}","`","is","the","Riemannian","gradient","operator","on",":","math",":","`","\\text","{","SU","}","(","2^N",")","`",".","By","discretizing","the","flow","above",",","we","see","that","a","step","of","this","optimizer","iterates","the","Riemannian","gradient","flow","on",":","math",":","`","\\text","{","SU","}","(","2^N",")","`","as","..","math",":",":","U^","{","(","t+1",")","}","=","\\exp\\left\\","{","\\epsilon\\",":","\\text","{","grad","}","f","(","U^","{","(","t",")","}",")","U^","{","(","t",")","}","\\right\\","}",",","where",":","math",":","`","\\epsilon","`","is","a","user-defined","hyperparameter","corresponding","to","the","step","size",".","The","Riemannian","gradient","in","the","Lie","algebra","is","given","by","..","math",":",":","\\text","{","grad","}","f","(","U^","{","(","t",")","}",")","=","-\\left","[","U","\\rho","U^\\dagger",",","H\\right","]",".","Hence","we","see","that","subsequent","steps","of","this","optimizer","will","append","the","unitary","generated","by","the","Riemannian","gradient","and","grow","the","circuit",".","The","exact","Riemannian","gradient","flow","on",":","math",":","`","\\text","{","SU","}","(","2^N",")","`","has","desirable","optimization","properties","that","can","guarantee","convergence","to","global","minima","under","mild","assumptions",".","However",",","this","comes","at","a","cost",".","Since",":","math",":","`","\\text","{","dim","}","(","\\text","{","SU","}","(","2^N",")",")","=","4^N-1","`",",","we","need","an","exponential","number","of","parameters","to","calculate","the","gradient",".","This","will","not","be","problematic","for","small","systems","(",":","math",":","`","N","<","5","`",")",",","but","will","quickly","get","out","of","control","as","the","number","of","qubits","increases",".","To","resolve","this","issue",",","we","can","restrict","the","Riemannian","gradient","to","a","subspace","of","the","Lie","algebra","and","calculate","an","approximate","Riemannian","gradient","flow",".","The","choice","of","restriction","will","affect","the","optimization","behavior","and","quality","of","the","final","solution",".","For","more","information","on","Riemannian","gradient","flows","on","Lie","groups","see","`","T.","Schulte-Herbrueggen","et",".","al",".","(","2008",")","<","https",":","\/\/arxiv.org\/abs\/0802.4195",">","`","_","and","the","application","to","quantum","circuits","`","Wiersema","and","Killoran","(","2022",")","<","https",":","\/\/arxiv.org\/abs\/2202.06976",">","`","_",".","Args",":","circuit","(",".QNode",")",":","a","user","defined","circuit","that","does","not","take","any","arguments","and","returns","the","expectation","value","of","a","``","qml.Hamiltonian","``",".","stepsize","(","float",")",":","the","user-defined","hyperparameter",":","math",":","`","\\epsilon","`",".","restriction","(",".Hamiltonian",")",":","Restrict","the","Lie","algebra","to","a","corresponding","subspace","of","the","full","Lie","algebra",".","This","restriction","should","be","passed","in","the","form","of","a","``","qml.Hamiltonian","``","that","consists","only","of","Pauli","words",".","exact","(","bool",")",":","Flag","that","indicates","wether","we","approximate","the","Riemannian","gradient","with","a","Trotterization","or","calculate","the","exact","evolution","via","a","matrix","exponential",".","The","latter","is","not","hardware","friendly","and","can","only","be","done","in","simulation",".","*","*","Examples","*","*","Define","a","Hamiltonian","cost","function","to","minimize",":",">",">",">","coeffs","=","[","-1.",",","-1.",",","-1",".","]",">",">",">","observables","=","[","qml.PauliX","(","0",")",",","qml.PauliZ","(","1",")",",","qml.PauliY","(","0",")","@","qml.PauliX","(","1",")","]",">",">",">","hamiltonian","=","qml.Hamiltonian","(","coeffs",",","observables",")","Create","an","initial","state","and","return","the","expectation","value","of","the","Hamiltonian",":",">",">",">","@","qml.qnode","(","qml.device","(","``","default.qubit","''",",","wires=2",")",")","...","def","quant_fun","(",")",":","...","qml.RX","(","0.1",",","wires=","[","0","]",")","...","qml.RY","(","0.5",",","wires=","[","1","]",")","...","qml.CNOT","(","wires=","[","0,1","]",")","...","qml.RY","(","0.6",",","wires=","[","0","]",")","...","return","qml.expval","(","hamiltonian",")","Instantiate","the","optimizer","with","the","initial","circuit","and","the","cost","function","and","set","the","stepsize","accordingly",":",">",">",">","opt","=","qml.RiemannianGradientOptimizer","(","circuit=quant_fun",",","stepsize=0.1",")","Applying","5","steps","gets","us","close","the","ground","state","of",":","math",":","`","E\\approx-2.23","`",":",">",">",">","for","step","in","range","(","6",")",":","...","circuit",",","cost","=","opt.step_and_cost","(",")","...","print","(","f","''","Step","{","step","}","-","cost","{","cost","}","''",")","Step","0","-","cost","-1.3351865007304005","Step","1","-","cost","-1.9937887238935206","Step","2","-","cost","-2.1524234485729834","Step","3","-","cost","-2.1955105378898487","Step","4","-","cost","-2.2137628169764256","Step","5","-","cost","-2.2234364822091575","The","optimized","circuit","is","returned","at","each","step",",","and","can","be","used","as","any","other","QNode",":",">",">",">","circuit","(",")","-2.2283086057521713"]
code: def __init__(
      self,
      circuit,
      stepsize=0.01,
      restriction=None,
      exact=False,
      trottersteps=1,
  ):
      if not isinstance(circuit, qml.QNode):
          raise TypeError(
              f"circuit must be a QNode, received {type(circuit)}"
          )
  
      self.circuit = circuit
      self.circuit.construct([], {})
      self.hamiltonian = circuit.func().obs
      if not isinstance(self.hamiltonian, qml.Hamiltonian):
          raise TypeError(
              f"circuit must return the expectation value of a Hamiltonian,"
              f"received {type(circuit.func().obs)}"
          )
      self.nqubits = len(circuit.device.wires)
  
      if self.nqubits > 4:
          warnings.warn(
              "The exact Riemannian gradient is exponentially expensive in the number of qubits, "
              f"optimizing a {self.nqubits} qubit circuit may be slow.",
              UserWarning,
          )
      if restriction is not None and not isinstance(
          restriction, qml.Hamiltonian
      ):
          raise TypeError(
              f"restriction must be a Hamiltonian, received {type(restriction)}"
          )
      (
          self.lie_algebra_basis_ops,
          self.lie_algebra_basis_names,
      ) = self.get_su_n_operators(restriction)
      self.exact = exact
      self.trottersteps = trottersteps
      self.coeffs, self.observables = self.hamiltonian.terms()
      self.stepsize = stepsize
  
file_path: pennylane/pennylane/optimize/riemannian_gradient.py
imports: import warnings
  from typing import Sequence, Callable
  import numpy
  from scipy.sparse.linalg import expm
  import pennylane
  from pennylane import transform
  from pennylane.tape import QuantumTape
  from pennylane.queuing import QueuingManager
label_desc: Use image node_id 1 to create a new RiemannianGradientOptimizer object  with example: obj = RiemannianGradientOptimizer(circuit, stepsize, restriction, exact, trottersteps)