qat.plugins.SPQEPlugin
This plugin is one of the two plugins that, once combined, allow performing projective quantum eigensolving (PQE, Stair et al.) on Qaptiva.
This plugin has to be used first in the stack, it adaptively prepares the ansatz based on the residues.
- class qat.plugins.SPQEPlugin(hf_state: int, max_excitation_order: int, selection_threshold: float = 1e-05, delta_t: float = 0.1)
Plugin implementation of the SPQE algorithm. The method is based on Stair and al. article.
This plugin performs the “macroiterations” described in the original work, namely it constructs a batch of parametric jobs which allow to measure the residues and that are sent to the lower part of the execution stack.
This plugin does not deal with the optimization process (“microiterations”), this is done by the PQEOptimizationPlugin plugin.
- Parameters
max_excitation_order (int) – Maximum order of the excitation operators used. e.g. max_excitation_order = 2 means the algorithm will use a dUCCSD ansatz
hf_state (int) – integer whose binary expansion represents the Hartree Fock state
selection_threshold (float, optional) – Threshold for the selective variant of the algorithm. Defaults to \(10^{-5}\).
delta_t (float, optional) – Parameter \(\Delta t\) used during the selection process, see Eq. (15). Defaults to \(10^{-2}\)
# Projective quantum eigensolver for the H2 molecule at r = 0.75
# we first set up the computation of the inputs for the H2 molecule,
# namely the Hamiltonian of the molecule and the parameters of the
# Hartree-Fock starting point
from qat.lang.AQASM import Program, X
from qat.qpus import LinAlg
from qat.fermion.chemistry.pyscf_tools import perform_pyscf_computation
from qat.fermion.chemistry import MolecularHamiltonian
from qat.fermion.chemistry.ucc import get_hf_ket
from qat.fermion.transforms import recode_integer, get_jw_code
from qat.plugins import SPQEPlugin, PQEOptimizationPlugin
r = 0.75
geometry = [("H", (0, 0, 0)), ("H", (0, 0, r))]
charge, spin = 0, 0
basis = "sto-3g"
(
rdm1,
orbital_energies,
nuclear_repulsion,
n_electrons,
one_body_integrals,
two_body_integrals,
info,
) = perform_pyscf_computation(
geometry=geometry, basis=basis, spin=spin, charge=charge, run_fci=True
)
mol_h = MolecularHamiltonian(
one_body_integrals, two_body_integrals, nuclear_repulsion
)
nqbits = rdm1.shape[0] * 2
ket_hf_init = get_hf_ket(n_electrons, nqbits=nqbits)
H_mol = mol_h.get_electronic_hamiltonian()
H_sp = H_mol.to_spin()
hf_init_sp = recode_integer(ket_hf_init, get_jw_code(H_sp.nbqbits))
# Here, we initialize the circuit with the Hartree-Fock state
# PQE will do the rest by adding parameterized gates corresponding to
# single, double, etc., excitations
prog = Program()
reg = prog.qalloc(nqbits)
for j, char in enumerate(format(hf_init_sp, "0" + str(nqbits) + "b")):
if char == "1":
prog.apply(X, reg[j])
job = prog.to_circ().to_job(observable=H_sp, nbshots=0)
PQE_plugin = SPQEPlugin(
hf_state=hf_init_sp,
max_excitation_order=2,
selection_threshold=1e-3,
delta_t=1e-1
)
PQEOptimization = PQEOptimizationPlugin(
orbital_energies,
hf_init_sp,
use_diis_bool=True,
maxiter=50,
diis_depth=6,
diis_threshold=1e-5,
equation_threshold=1e-5,
print_norm_during_optimization=False,
)
qpu = LinAlg()
stack = PQE_plugin | PQEOptimization | qpu
result_PQE = stack.submit(job)
print("E0 = ", result_PQE.value, ", err: ", abs(result_PQE.value - info["FCI"]))
E0 = -1.1371170673128344 , err: 3.289724048727294e-11