Quick-start guide
On this page we give a quick example of running a quantum computational chemistry calculation using InQuanto. This example evaluates the H2 electronic wave function in the minimal basis using the Unitary Coupled Cluster Singles Doubles Ansatz and finding parameters using the variational quantum eigensolver and a state vector (noiseless) backend.
Express database
Most quantum chemical calculations on a quantum computer start with a classical computation of
molecular integrals. In general this is achieved in InQuanto via separate extensions,
which interface to external classical quantum chemistry packages (for example inquanto-pyscf).
However, InQuanto also has a small internal database as part of its express
module.
This database contains molecular Hamiltonians, as well as other useful information,
for a variety of small systems. These examples can be easily loaded
and provide a simple way to start exploring InQuanto’s functionality.
In the cell below, we import the load_h5()
function which we then use to
load the H2 STO-3G example data. We then inspect its Hamiltonian terms, and print
its classically calculated CCSD energy, which is stored for easy comparison in the express database entry.
from inquanto.express import load_h5
h2_sto3g_data = load_h5("h2_sto3g.h5", as_tuple=True)
hamiltonian = h2_sto3g_data.hamiltonian_operator
print(hamiltonian.to_FermionOperator())
print(h2_sto3g_data.energy_ccsd)
(0.7430177069924179, ), (-1.270292724390438, F0^ F0 ), (-0.45680735030941033, F2^ F2 ), (-1.270292724390438, F1^ F1 ), (-0.45680735030941033, F3^ F3 ), (0.48890859745047327, F2^ F0^ F0 F2 ), (0.48890859745047327, F3^ F1^ F1 F3 ), (0.6800618575841273, F1^ F0^ F0 F1 ), (0.6685772770134888, F2^ F1^ F1 F2 ), (0.1796686795630157, F1^ F0^ F2 F3 ), (-0.17966867956301558, F2^ F1^ F0 F3 ), (-0.17966867956301558, F3^ F0^ F1 F2 ), (0.1796686795630155, F3^ F2^ F0 F1 ), (0.6685772770134888, F3^ F0^ F0 F3 ), (0.7028135332762804, F3^ F2^ F2 F3 )
-1.1368465754747636
VQE wrapper function
In the manual sections we demonstrate how a user can build a variety of tools
for performing quantum chemistry using InQuanto, but here we want a simple intuitive example that
“just runs”. To do this we will use the run_vqe()
function from express to run
a variational quantum eigensolver algorithm.
run_vqe()
requires the user to provide: an ansatz,
the Hamiltonian operator, and a pytket backend.
Optionally, the user can also choose whether run_vqe()
uses gradients,
what flavour of classical minimizer strategy to use, and the starting parameters for the variational cycle.
These are not required options, and when left undefined in the example below will default to i) using gradients, ii)
using the Scipy L-BFGS-B minimizer, and iii) starting with symbol parameters all set to zero.
As stated, run_vqe()
requires the Hamiltonian, an ansatz, and a backend.
To construct these we take the stored Fermionic operator data and qubit encode it using the
Jordan-Wigner mapping). Then we
prepare a 4 qubit ansatz circuit (corresponding to the 4 spin-orbitals of H2 STO-3G ) by
defining the FermionSpace and FermionState objects and feeding them into
the FermionSpaceAnsatzUCCSD
class (more here). Lastly
we import and instantiate a pytket state vector backend from Qiskit.
from inquanto.express import run_vqe
from inquanto.states import FermionState
from inquanto.spaces import FermionSpace
from inquanto.ansatzes import FermionSpaceAnsatzUCCSD
from pytket.extensions.qiskit import AerStateBackend
hamiltonian = load_h5("h2_sto3g.h5", as_tuple=True).hamiltonian_operator.qubit_encode()
space = FermionSpace(4)
state = FermionState([1, 1, 0, 0])
ansatz = FermionSpaceAnsatzUCCSD(fermion_space=space, fermion_state=state)
backend = AerStateBackend()
vqe = run_vqe(ansatz, hamiltonian, backend)
print(round(vqe.final_value, 8))
print(vqe.final_parameters)
# TIMER BLOCK-0 BEGINS AT 2024-07-19 14:21:00.756963
# TIMER BLOCK-0 ENDS - DURATION (s): 0.3177896 [0:00:00.317790]
-1.13684658
{d0: -0.10723347230091601, s0: 0.0, s1: 0.0}
After the VQE algorithm has converged we can inquire the total energy of the system usng final_value()
.
In UCCSD ansatz, this energy is equivalent to the CCSD energy
printed above (~1.1368465 Ha). We can also examine the parameters of the ansatz terms by printing the
final_parameters()
. These show that the singly excited terms (s) have no
contribution due to being symmetry forbidden but the doubly (d) excited term has significant weight in the optimized
wave function.
The above is just a quick example of how a user can run meaningful quantum computational chemistry calculations
easily using InQuanto. Whilst still using run_vqe()
there are plenty of variables
to explore. For example, you can try loading a different system
with more electrons or orbitals from express, modify the FermionSpace
and FermionState
accordingly and run a bigger calculation.
Alternatively, you could examine how setting with_gradient=False
on run_vqe()
or modifying its
minimizer changes the time to converge. Or how about comparing the speed of different pytket state vector backends?
After you’re comfortable with this quick-start guide, we recommend diving into the manual or following further tutorials.
Note
The run_vqe()
method is only recommended for testing purposes, not for production purposes.
The method only permits state vector based pytket backends.
For example one may use the AerStateBackend or QulacsBackend (see info here).
As the run_vqe()
method only permits state vector it streamlines the selection and generation of the
computables and protocols. Specifically, under the hood, the Protocol,
which provides instructions for circuit measurement and post-processing, is set to SparseStatevectorProtocol
,
and the Computable is ExpectationValue
. Again, under the hood, the computables are
built (using build()
) and then ran (using run()
). For non-state vector
calculations, one must utilize a proper instance of AlgorithmVQE
, which is much more flexible than run_vqe()
.