class_docstr: Estimate the number of non-Clifford gates and logical qubits for a quantum phase estimation
  algorithm in second quantization with a double-factorized Hamiltonian.
  
  Atomic units are used throughout the class.
  
  Args:
      one_electron (array[array[float]]): one-electron integrals
      two_electron (tensor_like): two-electron integrals
      error (float): target error in the algorithm
      rank_r (int): rank of the first factorization of the two-electron integral tensor
      rank_m (int): average rank of the second factorization of the two-electron integral tensor
      tol_factor (float): threshold error value for discarding the negligible factors
      tol_eigval (float): threshold error value for discarding the negligible factor eigenvalues
      br (int): number of bits for ancilla qubit rotation
      alpha (int): number of bits for the keep register
      beta (int): number of bits for the rotation angles
      chemist_notation (bool): if True, the two-electron integrals need to be in chemist notation
  
  **Example**
  
  >>> symbols  = ['O', 'H', 'H']
  >>> geometry = np.array([[0.00000000,  0.00000000,  0.28377432],
  >>>                      [0.00000000,  1.45278171, -1.00662237],
  >>>                      [0.00000000, -1.45278171, -1.00662237]], requires_grad = False)
  >>> mol = qml.qchem.Molecule(symbols, geometry, basis_name='sto-3g')
  >>> core, one, two = qml.qchem.electron_integrals(mol)()
  >>> algo = DoubleFactorization(one, two)
  >>> print(algo.lamb,  # the 1-Norm of the Hamiltonian
  >>>       algo.gates, # estimated number of non-Clifford gates
  >>>       algo.qubits # estimated number of logical qubits
  >>>       )
  53.62085493277858 103969925 290
  
  .. details::
      :title: Theory
  
      To estimate the gate and qubit costs for implementing this method, the Hamiltonian needs to
      be factorized using the :func:`~.pennylane.qchem.factorize` function following
      [`PRX Quantum 2, 030305 (2021) <https://journals.aps.org/prxquantum/abstract/10.1103/PRXQuantum.2.030305>`_].
      The objective of the factorization is to find a set of symmetric matrices, :math:`L^{(r)}`,
      such that the two-electron integral tensor in
      `chemist notation <http://vergil.chemistry.gatech.edu/notes/permsymm/permsymm.pdf>`_,
      :math:`V`, can be computed as
  
      .. math::
  
             V_{ijkl} = \sum_r^R L_{ij}^{(r)} L_{kl}^{(r) T},
  
      with the rank :math:`R \leq n^2`, where :math:`n` is the number of molecular orbitals. The
      matrices :math:`L^{(r)}` are diagonalized and for each matrix the eigenvalues that are
      smaller than a given threshold (and their corresponding eigenvectors) are discarded. The
      average number of the retained eigenvalues, :math:`M`, determines the rank of the second
      factorization step. The 1-norm of the Hamiltonian can then be computed using the
      :func:`~.pennylane.resource.DoubleFactorization.norm` function from the electron integrals
      and the eigenvalues of the matrices :math:`L^{(r)}`.
  
      The total number of gates and qubits for implementing the quantum phase estimation algorithm
      for the given Hamiltonian can then be computed using the functions
      :func:`~.pennylane.resource.DoubleFactorization.gate_cost` and
      :func:`~.pennylane.resource.DoubleFactorization.qubit_cost` with a target error that has the
      default value of 0.0016 Ha (chemical accuracy). The costs are computed using Eqs. (C39-C40)
      of [`PRX Quantum 2, 030305 (2021) <https://journals.aps.org/prxquantum/abstract/10.1103/PRXQuantum.2.030305>`_].
class_docstr_tok: ["Estimate","the","number","of","non-Clifford","gates","and","logical","qubits","for","a","quantum","phase","estimation","algorithm","in","second","quantization","with","a","double-factorized","Hamiltonian",".","Atomic","units","are","used","throughout","the","class",".","Args",":","one_electron","(","array","[","array","[","float","]","]",")",":","one-electron","integrals","two_electron","(","tensor_like",")",":","two-electron","integrals","error","(","float",")",":","target","error","in","the","algorithm","rank_r","(","int",")",":","rank","of","the","first","factorization","of","the","two-electron","integral","tensor","rank_m","(","int",")",":","average","rank","of","the","second","factorization","of","the","two-electron","integral","tensor","tol_factor","(","float",")",":","threshold","error","value","for","discarding","the","negligible","factors","tol_eigval","(","float",")",":","threshold","error","value","for","discarding","the","negligible","factor","eigenvalues","br","(","int",")",":","number","of","bits","for","ancilla","qubit","rotation","alpha","(","int",")",":","number","of","bits","for","the","keep","register","beta","(","int",")",":","number","of","bits","for","the","rotation","angles","chemist_notation","(","bool",")",":","if","True",",","the","two-electron","integrals","need","to","be","in","chemist","notation","*","*","Example","*","*",">",">",">","symbols","=","[","'","O","'",",","'","H","'",",","'","H","'","]",">",">",">","geometry","=","np.array","(","[","[","0.00000000",",","0.00000000",",","0.28377432","]",",",">",">",">","[","0.00000000",",","1.45278171",",","-1.00662237","]",",",">",">",">","[","0.00000000",",","-1.45278171",",","-1.00662237","]","]",",","requires_grad","=","False",")",">",">",">","mol","=","qml.qchem.Molecule","(","symbols",",","geometry",",","basis_name='sto-3g","'",")",">",">",">","core",",","one",",","two","=","qml.qchem.electron_integrals","(","mol",")","(",")",">",">",">","algo","=","DoubleFactorization","(","one",",","two",")",">",">",">","print","(","algo.lamb",",","#","the","1-Norm","of","the","Hamiltonian",">",">",">","algo.gates",",","#","estimated","number","of","non-Clifford","gates",">",">",">","algo.qubits","#","estimated","number","of","logical","qubits",">",">",">",")","53.62085493277858","103969925","290","..","details",":",":",":","title",":","Theory","To","estimate","the","gate","and","qubit","costs","for","implementing","this","method",",","the","Hamiltonian","needs","to","be","factorized","using","the",":","func",":","`","~.pennylane.qchem.factorize","`","function","following","[","`","PRX","Quantum","2",",","030305","(","2021",")","<","https",":","\/\/journals.aps.org\/prxquantum\/abstract\/10.1103\/PRXQuantum.2.030305",">","`","_","]",".","The","objective","of","the","factorization","is","to","find","a","set","of","symmetric","matrices",",",":","math",":","`","L^","{","(","r",")","}","`",",","such","that","the","two-electron","integral","tensor","in","`","chemist","notation","<","http",":","\/\/vergil.chemistry.gatech.edu\/notes\/permsymm\/permsymm.pdf",">","`","_",",",":","math",":","`","V","`",",","can","be","computed","as","..","math",":",":","V_","{","ijkl","}","=","\\sum_r^R","L_","{","ij","}","^","{","(","r",")","}","L_","{","kl","}","^","{","(","r",")","T","}",",","with","the","rank",":","math",":","`","R","\\leq","n^2","`",",","where",":","math",":","`","n","`","is","the","number","of","molecular","orbitals",".","The","matrices",":","math",":","`","L^","{","(","r",")","}","`","are","diagonalized","and","for","each","matrix","the","eigenvalues","that","are","smaller","than","a","given","threshold","(","and","their","corresponding","eigenvectors",")","are","discarded",".","The","average","number","of","the","retained","eigenvalues",",",":","math",":","`","M","`",",","determines","the","rank","of","the","second","factorization","step",".","The","1-norm","of","the","Hamiltonian","can","then","be","computed","using","the",":","func",":","`","~.pennylane.resource.DoubleFactorization.norm","`","function","from","the","electron","integrals","and","the","eigenvalues","of","the","matrices",":","math",":","`","L^","{","(","r",")","}","`",".","The","total","number","of","gates","and","qubits","for","implementing","the","quantum","phase","estimation","algorithm","for","the","given","Hamiltonian","can","then","be","computed","using","the","functions",":","func",":","`","~.pennylane.resource.DoubleFactorization.gate_cost","`","and",":","func",":","`","~.pennylane.resource.DoubleFactorization.qubit_cost","`","with","a","target","error","that","has","the","default","value","of","0.0016","Ha","(","chemical","accuracy",")",".","The","costs","are","computed","using","Eqs",".","(","C39-C40",")","of","[","`","PRX","Quantum","2",",","030305","(","2021",")","<","https",":","\/\/journals.aps.org\/prxquantum\/abstract\/10.1103\/PRXQuantum.2.030305",">","`","_","]","."]
docstr: Return the number of logical qubits needed to implement the double factorization method.
  
  The expression for computing the cost is taken from Eq. (C40) of
  [`PRX Quantum 2, 030305 (2021) <https://journals.aps.org/prxquantum/abstract/10.1103/PRXQuantum.2.030305>`_].
  
  Args:
      n (int): number of molecular spin-orbitals
      lamb (float): 1-norm of a second-quantized Hamiltonian
      error (float): target error in the algorithm
      rank_r (int): rank of the first factorization of the two-electron integral tensor
      rank_m (float): average rank of the second factorization of the two-electron tensor
      rank_max (int): maximum rank of the second factorization of the two-electron tensor
      br (int): number of bits for ancilla qubit rotation
      alpha (int): number of bits for the keep register
      beta (int): number of bits for the rotation angles
  
  Returns:
      int: number of logical qubits for the double factorization method
  
  **Example**
  
  >>> n = 14
  >>> lamb = 52.98761457453095
  >>> error = 0.001
  >>> rank_r = 26
  >>> rank_m = 5.5
  >>> rank_max = 7
  >>> br = 7
  >>> alpha = 10
  >>> beta = 20
  >>> qubit_cost(n, lamb, error, rank_r, rank_m, rank_max, br, alpha, beta)
  292
docstr_tok: ["Return","the","number","of","logical","qubits","needed","to","implement","the","double","factorization","method",".","The","expression","for","computing","the","cost","is","taken","from","Eq",".","(","C40",")","of","[","`","PRX","Quantum","2",",","030305","(","2021",")","<","https",":","\/\/journals.aps.org\/prxquantum\/abstract\/10.1103\/PRXQuantum.2.030305",">","`","_","]",".","Args",":","n","(","int",")",":","number","of","molecular","spin-orbitals","lamb","(","float",")",":","1-norm","of","a","second-quantized","Hamiltonian","error","(","float",")",":","target","error","in","the","algorithm","rank_r","(","int",")",":","rank","of","the","first","factorization","of","the","two-electron","integral","tensor","rank_m","(","float",")",":","average","rank","of","the","second","factorization","of","the","two-electron","tensor","rank_max","(","int",")",":","maximum","rank","of","the","second","factorization","of","the","two-electron","tensor","br","(","int",")",":","number","of","bits","for","ancilla","qubit","rotation","alpha","(","int",")",":","number","of","bits","for","the","keep","register","beta","(","int",")",":","number","of","bits","for","the","rotation","angles","Returns",":","int",":","number","of","logical","qubits","for","the","double","factorization","method","*","*","Example","*","*",">",">",">","n","=","14",">",">",">","lamb","=","52.98761457453095",">",">",">","error","=","0.001",">",">",">","rank_r","=","26",">",">",">","rank_m","=","5.5",">",">",">","rank_max","=","7",">",">",">","br","=","7",">",">",">","alpha","=","10",">",">",">","beta","=","20",">",">",">","qubit_cost","(","n",",","lamb",",","error",",","rank_r",",","rank_m",",","rank_max",",","br",",","alpha",",","beta",")","292"]
code: def qubit_cost(
      n, lamb, error, rank_r, rank_m, rank_max, br=7, alpha=10, beta=20
  ):
      r"""Return the number of logical qubits needed to implement the double factorization method.
  
      The expression for computing the cost is taken from Eq. (C40) of
      [`PRX Quantum 2, 030305 (2021) <https://journals.aps.org/prxquantum/abstract/10.1103/PRXQuantum.2.030305>`_].
  
      Args:
          n (int): number of molecular spin-orbitals
          lamb (float): 1-norm of a second-quantized Hamiltonian
          error (float): target error in the algorithm
          rank_r (int): rank of the first factorization of the two-electron integral tensor
          rank_m (float): average rank of the second factorization of the two-electron tensor
          rank_max (int): maximum rank of the second factorization of the two-electron tensor
          br (int): number of bits for ancilla qubit rotation
          alpha (int): number of bits for the keep register
          beta (int): number of bits for the rotation angles
  
      Returns:
          int: number of logical qubits for the double factorization method
  
      **Example**
  
      >>> n = 14
      >>> lamb = 52.98761457453095
      >>> error = 0.001
      >>> rank_r = 26
      >>> rank_m = 5.5
      >>> rank_max = 7
      >>> br = 7
      >>> alpha = 10
      >>> beta = 20
      >>> qubit_cost(n, lamb, error, rank_r, rank_m, rank_max, br, alpha, beta)
      292
      """
      if n <= 0 or not isinstance(n, (int, np.integer)) or n % 2 != 0:
          raise ValueError(
              "The number of spin-orbitals must be a positive even integer."
          )
  
      if error <= 0.0:
          raise ValueError(
              "The target error must be greater than zero."
          )
  
      if lamb <= 0.0:
          raise ValueError("The 1-norm must be greater than zero.")
  
      if rank_r <= 0 or not isinstance(rank_r, int):
          raise ValueError(
              "The rank of the first factorization step must be a positive integer."
          )
  
      if rank_m <= 0:
          raise ValueError(
              "The rank of the second factorization step must be a positive number."
          )
  
      if rank_max <= 0 or not isinstance(rank_max, int):
          raise ValueError(
              "The maximum rank of the second factorization step must be a positive integer."
          )
  
      if br <= 0 or not isinstance(br, int):
          raise ValueError("br must be a positive integer.")
  
      if alpha <= 0 or not isinstance(alpha, int):
          raise ValueError("alpha must be a positive integer.")
  
      if beta <= 0 or not isinstance(beta, int):
          raise ValueError("beta must be a positive integer.")
  
      rank_rm = rank_r * rank_m
  
      nxi = np.ceil(
          np.log2(rank_max)
      )  # Eq. (C14) of PRX Quantum 2, 030305 (2021)
      nl = np.ceil(
          np.log2(rank_r + 1)
      )  # Eq. (C14) of PRX Quantum 2, 030305 (2021)
      nlxi = np.ceil(
          np.log2(rank_rm + n / 2)
      )  # Eq. (C15) of PRX Quantum 2, 030305 (2021)
  
      bo = (
          nxi + nlxi + br + 1
      )  # Eq. (C29) of PRX Quantum 2, 030305 (2021)
      bp2 = nxi + alpha + 2  # Eq. (C31) of PRX Quantum 2, 030305 (2021)
      # kr is taken from Eq. (C39) of PRX Quantum 2, 030305 (2021)
      kr = DoubleFactorization._qrom_cost(
          (rank_rm, n / 2, rank_rm, n * beta, 0)
      )[1]
  
      # the cost is computed using Eq. (C40) of PRX Quantum 2, 030305 (2021)
      e_cost = DoubleFactorization.estimation_cost(lamb, error)
      cost = n + 2 * nl + nxi + 3 * alpha + beta + bo + bp2
      cost += kr * n * beta / 2 + 2 * np.ceil(np.log2(e_cost + 1)) + 7
  
      return int(cost)
  
file_path: pennylane/pennylane/resource/second_quantization.py
imports: import numpy
  from pennylane.operation import AnyWires, Operation
  from pennylane.qchem import factorize
label_desc: Use image node_id 8 for calling the DoubleFactorization obj's underlying member method code with example usage: obj.qubit_cost(n, lamb, error, rank_r, rank_m, rank_max, br, alpha, beta) and returns: int