class_docstr: Implements the k-Unitary Pair Coupled-Cluster Generalized Singles and Doubles (k-UpCCGSD) ansatz.
  
  The k-UpCCGSD ansatz calls the :func:`~.FermionicSingleExcitation` and :func:`~.FermionicDoubleExcitation`
  templates to exponentiate the product of :math:`k` generalized singles and pair coupled-cluster doubles
  excitation operators. Here, "generalized" means that the single and double excitation terms do not
  distinguish between occupied and unoccupied orbitals. Additionally, the term "pair coupled-cluster"
  refers to the fact that the double excitations contain only those two-body excitations that move a
  pair of electrons from one spatial orbital to another. This k-UpCCGSD belongs to the family of Unitary
  Coupled Cluster (UCC) based ansätze, commonly used to solve quantum chemistry problems on quantum computers.
  
  The k-UpCCGSD unitary, within the first-order Trotter approximation for a given integer :math:`k`, is given by:
  
  .. math::
  
      \hat{U}(\vec{\theta}) =
      \prod_{l=1}^{k} \bigg(\prod_{p,r}\exp{\Big\{
      \theta_{r}^{p}(\hat{c}^{\dagger}_p\hat{c}_r - \text{H.c.})\Big\}}
      \ \prod_{i,j} \Big\{\exp{\theta_{j_\alpha j_\beta}^{i_\alpha i_\beta}
      (\hat{c}^{\dagger}_{i_\alpha}\hat{c}^{\dagger}_{i_\beta}
      \hat{c}_{j_\alpha}\hat{c}_{j_\beta} - \text{H.c.}) \Big\}}\bigg)
  
  where :math:`\hat{c}` and :math:`\hat{c}^{\dagger}` are the fermionic annihilation and creation operators.
  The indices :math:`p, q` run over the spin orbitals and :math:`i, j` run over the spatial orbitals. The
  singles and paired doubles amplitudes :math:`\theta_{r}^{p}` and
  :math:`\theta_{j_\alpha j_\beta}^{i_\alpha i_\beta}` represent the set of variational parameters.
  
  Args:
      weights (tensor_like): Tensor containing the parameters :math:`\theta_{pr}` and :math:`\theta_{pqrs}`
          entering the Z rotation in :func:`~.FermionicSingleExcitation` and :func:`~.FermionicDoubleExcitation`.
          These parameters are the coupled-cluster amplitudes that need to be optimized for each generalized
          single and pair double excitation terms.
      wires (Iterable): wires that the template acts on
      k (int): Number of times UpCCGSD unitary is repeated.
      delta_sz (int): Specifies the selection rule ``sz[p] - sz[r] = delta_sz``
          for the spin-projection ``sz`` of the orbitals involved in the generalized single excitations.
          ``delta_sz`` can take the values :math:`0` and :math:`\pm 1`.
      init_state (array[int]): Length ``len(wires)`` occupation-number vector representing the
          HF state. ``init_state`` is used to initialize the wires.
  
  .. details::
      :title: Usage Details
  
      #. The number of wires has to be equal to the number of
         spin-orbitals included in the active space, and should be even.
  
      #. The number of trainable parameters scales linearly with the number of layers as
         :math:`2 k n`, where :math:`n` is the total number of
         generalized singles and paired doubles excitation terms.
  
      An example of how to use this template is shown below:
  
      .. code-block:: python
  
          import pennylane as qml
          from pennylane import numpy as np
  
          # Build the electronic Hamiltonian
          symbols = ["H", "H"]
          coordinates = np.array([0.0, 0.0, -0.6614, 0.0, 0.0, 0.6614])
          H, qubits = qml.qchem.molecular_hamiltonian(symbols, coordinates)
  
          # Define the Hartree-Fock state
          electrons = 2
          ref_state = qml.qchem.hf_state(electrons, qubits)
  
          # Define the device
          dev = qml.device('default.qubit', wires=qubits)
  
          # Define the ansatz
          @qml.qnode(dev)
          def ansatz(weights):
              qml.kUpCCGSD(weights, wires=[0, 1, 2, 3],
                              k=1, delta_sz=0, init_state=ref_state)
              return qml.expval(H)
  
          # Get the shape of the weights for this template
          layers = 1
          shape = qml.kUpCCGSD.shape(k=layers,
                              n_wires=qubits, delta_sz=0)
  
          # Initialize the weight tensors
          np.random.seed(24)
          weights = np.random.random(size=shape)
  
          # Define the optimizer
          opt = qml.GradientDescentOptimizer(stepsize=0.4)
  
          # Store the values of the cost function
          energy = [ansatz(weights)]
  
          # Store the values of the circuit weights
          angle = [weights]
          max_iterations = 100
          conv_tol = 1e-06
          for n in range(max_iterations):
              weights, prev_energy = opt.step_and_cost(ansatz, weights)
              energy.append(ansatz(weights))
              angle.append(weights)
              conv = np.abs(energy[-1] - prev_energy)
              if n % 4 == 0:
                  print(f"Step = {n},  Energy = {energy[-1]:.8f} Ha")
              if conv <= conv_tol:
                  break
  
          print("\n" f"Final value of the ground-state energy = {energy[-1]:.8f} Ha")
          print("\n" f"Optimal value of the circuit parameters = {angle[-1]}")
  
      .. code-block:: none
  
          Step = 0,  Energy = -1.08949110 Ha
          Step = 4,  Energy = -1.13370605 Ha
          Step = 8,  Energy = -1.13581648 Ha
          Step = 12,  Energy = -1.13613171 Ha
          Step = 16,  Energy = -1.13618030 Ha
          Step = 20,  Energy = -1.13618779 Ha
  
          Final value of the ground-state energy = -1.13618779 Ha
  
          Optimal value of the circuit parameters = [[0.97879636 0.46093583 0.98108824
          0.45864352 0.65531446 0.44558289]]
  
  
      **Parameter shape**
  
      The shape of the weights argument can be computed by the static method
      :meth:`~.kUpCCGSD.shape` and used when creating randomly
      initialised weight tensors:
  
      .. code-block:: python
  
          shape = qml.kUpCCGSD.shape(n_layers=2, n_wires=4)
          weights = np.random.random(size=shape)
  
      >>> weights.shape
      (2, 6)
class_docstr_tok: ["Implements","the","k-Unitary","Pair","Coupled-Cluster","Generalized","Singles","and","Doubles","(","k-UpCCGSD",")","ansatz",".","The","k-UpCCGSD","ansatz","calls","the",":","func",":","`","~.FermionicSingleExcitation","`","and",":","func",":","`","~.FermionicDoubleExcitation","`","templates","to","exponentiate","the","product","of",":","math",":","`","k","`","generalized","singles","and","pair","coupled-cluster","doubles","excitation","operators",".","Here",",","``","generalized","''","means","that","the","single","and","double","excitation","terms","do","not","distinguish","between","occupied","and","unoccupied","orbitals",".","Additionally",",","the","term","``","pair","coupled-cluster","''","refers","to","the","fact","that","the","double","excitations","contain","only","those","two-body","excitations","that","move","a","pair","of","electrons","from","one","spatial","orbital","to","another",".","This","k-UpCCGSD","belongs","to","the","family","of","Unitary","Coupled","Cluster","(","UCC",")","based","ans\u00e4tze",",","commonly","used","to","solve","quantum","chemistry","problems","on","quantum","computers",".","The","k-UpCCGSD","unitary",",","within","the","first-order","Trotter","approximation","for","a","given","integer",":","math",":","`","k","`",",","is","given","by",":","..","math",":",":","\\hat","{","U","}","(","\\vec","{","\\theta","}",")","=","\\prod_","{","l=1","}","^","{","k","}","\\bigg","(","\\prod_","{","p",",","r","}","\\exp","{","\\Big\\","{","\\theta_","{","r","}","^","{","p","}","(","\\hat","{","c","}","^","{","\\dagger","}","_p\\hat","{","c","}","_r","-","\\text","{","H.c.","}",")","\\Big\\","}","}","\\","\\prod_","{","i",",","j","}","\\Big\\","{","\\exp","{","\\theta_","{","j_\\alpha","j_\\beta","}","^","{","i_\\alpha","i_\\beta","}","(","\\hat","{","c","}","^","{","\\dagger","}","_","{","i_\\alpha","}","\\hat","{","c","}","^","{","\\dagger","}","_","{","i_\\beta","}","\\hat","{","c","}","_","{","j_\\alpha","}","\\hat","{","c","}","_","{","j_\\beta","}","-","\\text","{","H.c.","}",")","\\Big\\","}","}","\\bigg",")","where",":","math",":","`","\\hat","{","c","}","`","and",":","math",":","`","\\hat","{","c","}","^","{","\\dagger","}","`","are","the","fermionic","annihilation","and","creation","operators",".","The","indices",":","math",":","`","p",",","q","`","run","over","the","spin","orbitals","and",":","math",":","`","i",",","j","`","run","over","the","spatial","orbitals",".","The","singles","and","paired","doubles","amplitudes",":","math",":","`","\\theta_","{","r","}","^","{","p","}","`","and",":","math",":","`","\\theta_","{","j_\\alpha","j_\\beta","}","^","{","i_\\alpha","i_\\beta","}","`","represent","the","set","of","variational","parameters",".","Args",":","weights","(","tensor_like",")",":","Tensor","containing","the","parameters",":","math",":","`","\\theta_","{","pr","}","`","and",":","math",":","`","\\theta_","{","pqrs","}","`","entering","the","Z","rotation","in",":","func",":","`","~.FermionicSingleExcitation","`","and",":","func",":","`","~.FermionicDoubleExcitation","`",".","These","parameters","are","the","coupled-cluster","amplitudes","that","need","to","be","optimized","for","each","generalized","single","and","pair","double","excitation","terms",".","wires","(","Iterable",")",":","wires","that","the","template","acts","on","k","(","int",")",":","Number","of","times","UpCCGSD","unitary","is","repeated",".","delta_sz","(","int",")",":","Specifies","the","selection","rule","``","sz","[","p","]","-","sz","[","r","]","=","delta_sz","``","for","the","spin-projection","``","sz","``","of","the","orbitals","involved","in","the","generalized","single","excitations",".","``","delta_sz","``","can","take","the","values",":","math",":","`","0","`","and",":","math",":","`","\\pm","1","`",".","init_state","(","array","[","int","]",")",":","Length","``","len","(","wires",")","``","occupation-number","vector","representing","the","HF","state",".","``","init_state","``","is","used","to","initialize","the","wires",".","..","details",":",":",":","title",":","Usage","Details","#",".","The","number","of","wires","has","to","be","equal","to","the","number","of","spin-orbitals","included","in","the","active","space",",","and","should","be","even",".","#",".","The","number","of","trainable","parameters","scales","linearly","with","the","number","of","layers","as",":","math",":","`","2","k","n","`",",","where",":","math",":","`","n","`","is","the","total","number","of","generalized","singles","and","paired","doubles","excitation","terms",".","An","example","of","how","to","use","this","template","is","shown","below",":","..","code-block",":",":","python","import","pennylane","as","qml","from","pennylane","import","numpy","as","np","#","Build","the","electronic","Hamiltonian","symbols","=","[","``","H","''",",","``","H","''","]","coordinates","=","np.array","(","[","0.0",",","0.0",",","-0.6614",",","0.0",",","0.0",",","0.6614","]",")","H",",","qubits","=","qml.qchem.molecular_hamiltonian","(","symbols",",","coordinates",")","#","Define","the","Hartree-Fock","state","electrons","=","2","ref_state","=","qml.qchem.hf_state","(","electrons",",","qubits",")","#","Define","the","device","dev","=","qml.device","(","'default.qubit","'",",","wires=qubits",")","#","Define","the","ansatz","@","qml.qnode","(","dev",")","def","ansatz","(","weights",")",":","qml.kUpCCGSD","(","weights",",","wires=","[","0",",","1",",","2",",","3","]",",","k=1",",","delta_sz=0",",","init_state=ref_state",")","return","qml.expval","(","H",")","#","Get","the","shape","of","the","weights","for","this","template","layers","=","1","shape","=","qml.kUpCCGSD.shape","(","k=layers",",","n_wires=qubits",",","delta_sz=0",")","#","Initialize","the","weight","tensors","np.random.seed","(","24",")","weights","=","np.random.random","(","size=shape",")","#","Define","the","optimizer","opt","=","qml.GradientDescentOptimizer","(","stepsize=0.4",")","#","Store","the","values","of","the","cost","function","energy","=","[","ansatz","(","weights",")","]","#","Store","the","values","of","the","circuit","weights","angle","=","[","weights","]","max_iterations","=","100","conv_tol","=","1e-06","for","n","in","range","(","max_iterations",")",":","weights",",","prev_energy","=","opt.step_and_cost","(","ansatz",",","weights",")","energy.append","(","ansatz","(","weights",")",")","angle.append","(","weights",")","conv","=","np.abs","(","energy","[","-1","]","-","prev_energy",")","if","n","%","4","==","0",":","print","(","f","''","Step","=","{","n","}",",","Energy","=","{","energy","[","-1","]",":",".8f","}","Ha","''",")","if","conv","<","=","conv_tol",":","break","print","(","``","\\n","''","f","''","Final","value","of","the","ground-state","energy","=","{","energy","[","-1","]",":",".8f","}","Ha","''",")","print","(","``","\\n","''","f","''","Optimal","value","of","the","circuit","parameters","=","{","angle","[","-1","]","}","''",")","..","code-block",":",":","none","Step","=","0",",","Energy","=","-1.08949110","Ha","Step","=","4",",","Energy","=","-1.13370605","Ha","Step","=","8",",","Energy","=","-1.13581648","Ha","Step","=","12",",","Energy","=","-1.13613171","Ha","Step","=","16",",","Energy","=","-1.13618030","Ha","Step","=","20",",","Energy","=","-1.13618779","Ha","Final","value","of","the","ground-state","energy","=","-1.13618779","Ha","Optimal","value","of","the","circuit","parameters","=","[","[","0.97879636","0.46093583","0.98108824","0.45864352","0.65531446","0.44558289","]","]","*","*","Parameter","shape","*","*","The","shape","of","the","weights","argument","can","be","computed","by","the","static","method",":","meth",":","`","~.kUpCCGSD.shape","`","and","used","when","creating","randomly","initialised","weight","tensors",":","..","code-block",":",":","python","shape","=","qml.kUpCCGSD.shape","(","n_layers=2",",","n_wires=4",")","weights","=","np.random.random","(","size=shape",")",">",">",">","weights.shape","(","2",",","6",")"]
code: def __init__(
      self, weights, wires, k=1, delta_sz=0, init_state=None, id=None
  ):
      if len(wires) < 4:
          raise ValueError(
              f"Requires at least four wires; got {len(wires)} wires."
          )
      if len(wires) % 2:
          raise ValueError(
              f"Requires even number of wires; got {len(wires)} wires."
          )
  
      if k < 1:
          raise ValueError(f"Requires k to be at least 1; got {k}.")
  
      if delta_sz not in [-1, 0, 1]:
          raise ValueError(
              f"Requires delta_sz to be one of ±1 or 0; got {delta_sz}."
          )
  
      s_wires = generalized_singles(list(wires), delta_sz)
      d_wires = generalized_pair_doubles(list(wires))
  
      shape = qml.math.shape(weights)
      if shape != (
          k,
          len(s_wires) + len(d_wires),
      ):
          raise ValueError(
              f"Weights tensor must be of shape {(k, len(s_wires) + len(d_wires),)}; got {shape}."
          )
  
      init_state = qml.math.toarray(init_state)
      if init_state.dtype != np.dtype("int"):
          raise ValueError(
              f"Elements of 'init_state' must be integers; got {init_state.dtype}"
          )
  
      self._hyperparameters = {
          "init_state": init_state,
          "s_wires": s_wires,
          "d_wires": d_wires,
          "k": k,
          "delta_sz": delta_sz,
      }
      super().__init__(weights, wires=wires, id=id)
  
file_path: pennylane/pennylane/templates/subroutines/kupccgsd.py
imports: import numpy
  import pennylane
  from pennylane.operation import Operation, AnyWires
label_desc: Use image node_id 2 to create a new kUpCCGSD object from inherited base classes: Operation with example: obj = kUpCCGSD(weights, wires, k, delta_sz, init_state, id)