Code
qcr:2606.24663.1

VQE for Molecular Chemistry with Amazon Braket

The Variational Quantum Eigensolver (VQE) is the flagship near-term quantum algorithm for quantum chemistry, and this Amazon Braket notebook applies it to compute the potential energy surface of the hydrogen molecule. VQE finds the ground-state energy of a molecule's electronic Hamiltonian by preparing a parameterized trial state (ansatz) on a quantum computer, measuring its energy expectation value, and using a classical optimizer to vary the parameters until the energy is minimized, exploiting the variational principle that any trial energy upper-bounds the true ground state. The notebook walks through the full pipeline: using OpenFermion and a classical chemistry backend to build the molecular Hamiltonian and map it to qubit operators, constructing an ansatz circuit with the Braket SDK, estimating the energy by measuring the required Pauli terms on a Braket simulator, and driving the classical optimization loop. By sweeping the interatomic distance and re-optimizing at each point, it traces out the hydrogen molecule's potential energy surface and recovers the equilibrium bond length. It is a complete, worked demonstration of variational quantum chemistry, one of the most promising applications of near-term quantum hardware, implemented with Amazon Braket.
Chemistry
Qubit
Circuit-based
Uploaded 3 days ago
44
Views
GitHub582
Citing this entry? Use this QCR ID
Uploaded by
QL
QCR Librarian

Overview

amazon-braket/amazon-braket-examples
582261
In [ ]:
# --- Setup cell added by QCR (not part of the original tutorial) ---
# Source: amazon-braket/amazon-braket-examples @ 0c0818f315479aab9deebed7e7ed7533ac581923, Apache License 2.0.
# Installs the example's dependencies. If a later cell still reports a missing
# package, restart the runtime/kernel and run again from the top.
%pip install -q amazon-braket-sdk==1.117.3 openfermion==1.7.1 openfermionpyscf==0.5 matplotlib

Introduction

In this notebook, we illustrate how to implement the Variational Quantum Eigensolver (VQE) algorithm in Amazon Braket SDK to compute the potential energy surface (PES) for the Hydrogen molecule. Specifically, we illustrate the following features of Amazon Braket SDK:

  • LocalSimulator which allows one to simulate quantum circuits on their local machine
  • Construction of the ansatz circuit for VQE in Braket SDK
  • Computing expectation values of the individual terms in the Hamiltonian in Braket SDK

Problem formulation

In computational chemistry, we are typically interested in finding the ground-state energy (i.e., minimum energy) of a molecule for a given configuration of atomic positions. This is accomplished by finding the lowest eigenvalues and eigenstates of the molecular Hamiltonian.

Molecular Hamiltonian

In atomic units, the full molecular Hamiltonian takes the form [1],

where and label the electrons and nuclei respectively. Here and denote the electron and nucleus positions, denotes nuclear charge, and denotes nuclear mass respectively. The first two terms in Eq.(1) represent the electronic and nuclear kinetic energy, while the remaining terms denote the Coulombic interaction between the nuclei and electrons, amongst the electrons, and amongst the nuclei respectively.

Since we are mostly interested in the electronic structure of the molecule, we invoke the Born-Oppenheimer approximation, which is based on the fact that nuclei are over a thousand times heavier than electrons. This approximation allows us to reduce the problem to finding the eigenvalues of the following electronic Hamiltonian for a given nuclear configuration [1], i.e., fixed set of nuclear positions ,

Second quantization

In order to determine the eigenvalues and eigenstates of the electronic Hamiltonian of a molecule given in Eq. (2), we start with a set of single-electron basis functions (also called spin orbitals), , where denotes the spatial position and spin of the -th electron. The many-electron wavefunction is expressed as a Slater determinant of these basis functions, i.e., as an antisymmetrized product of the single-electron basis functions, so that the electrons automatically satisfy the Pauli exclusion principle. While the total number of single-electron basis functions considered , is typically larger than the total number of electrons , in the molecule, the electrons can only occupy () of these orbitals in a Slater determinant, i.e., a Slater determinant contains only occupied orbitals [1]. Since any Slater determinant of the basis functions is uniquely determined by which orbitals are occupied, a Slater determinant can be represented in an abstract vector space, called the Fock space, by an occupation number vector where each is either 0 or 1 depending on whether the -th orbitals is unoccupied or occupied respectively in the Slater determinant.

Next, we introduce a set of operators , called the fermion annihilation and creation operators respectively, corresponding to each of the basis functions , which satisfy the anticommutation relations,

where the anticommutator of two operators and is defined as and denotes the Kronecker delta.

Expressing the electronic Hamiltonian in Eq. (2) in terms of these fermionic operators we get [1],

where,

and

Basis sets

A variety of basis sets are used in computational chemistry depending on the chemical system being studied and the accuracy required, e.g.,

Hartree-Fock method

The Hartree-Fock (HF) method is the starting point for most computational chemistry calculations of atoms and molecules [1]. The HF method aims to find the single-most dominant Slater determinant that best approximates the system wavefunction by optimizing the spatial form of the spin orbitals in a self-consistent fashion (hence, also called self-consistent field or SCF method) to minimize the energy of the wavefunction. The Slater determinant generated by the optimized spin orbitals (also known as canonical orbitals) computed from the HF method is used as the reference state for post Hartree-Fock methods that try to correct for some of the approximations in the HF method.

Post Hartree-Fock methods

There are a variety of post Hartree-Fock (post-HF) methods employed in classical computational chemistry to improve upon the accuracy of a simple HF computation to varying degrees [1], e.g.,

Mapping to quantum computer

In order to represent the electronic Hamiltonian of the molecular system under study, we need to map it to operators that act on the qubits of a quantum computer. There are various encoding techniques to accomplish this, e.g., parity encoding, Bravyi-Kitaev encoding, etc., but the simplest one is the Jordan-Wigner encoding [2].

Jordan-Wigner encoding

In the Jordan-Wigner (JW) encoding, we store the occupation number of an orbital in the -th qubit as either or depending on whether the orbital is unoccupied or occupied respectively. Correspondingly, the fermionic annihilation and creation operators are mapped to the qubit operators as

and

where , denotes the Pauli-Z matrix and denotes the tensor product. This shows that in the JW encoding, while the occupation of an orbital is stored locally, i.e., in a single qubit, the parity is stored non-locally. This makes JW encoding not as efficient compared to other encoding techniques, e.g., Bravyi-Kitaev encoding, but for small systems with a few qubits, the efficiency gap is not significant.

Variational Quantum Eigensolver

One of the most promising algorithms for performing quantum chemistry computations on the NISQ (noisy intermediate-scale quantum) era quantum computers we can currently use is the variational quantum eigensolver (VQE) [2]. VQE is a hybrid quantum-classical algorithm using the quantum computer only for a classically intractable subroutine and has been shown to be robust against noise [2,4], and capable of finding ground-state energies of small molecules using low-depth quantum circuits.

VQE is based on the Raleigh-Ritz variational principle: for a trial wavefunction parameterized by a vector parameter for a system with Hamiltonian , whose lowest energy eigenvalue is [2],

Thus, VQE reduces the problem of finding the ground-state energy of the system Hamiltonian to finding the optimum value of the vector parameter . The parameterized wavefunction is prepared on a quantum computer by applying a series of parameterized unitary gates (also called a parameterized circuit) to the qubits initialized in some reference state , e.g., a HF state, as [2]

As classical computers are unable to efficiently prepare, store and measure the expectation value of the Hamiltonian for the parameterized wavefunction , we use the quantum computer for this subroutine, and then use the classical computer to update the parameters using an optimization algorithm.

To complete the specification of VQE, one needs to specify the form of the parameterized wavefunction , known as the ansatz. A popular chemically-inspired ansatz for VQE is the unitary coupled cluster ansatz truncated to singles and doubles excitations (UCCSD).

UCCSD ansatz

The unitary coupled cluster (UCC) method is an extension of the coupled-cluster (CC) method, which is one of the most popular post-HF methods [2]. In the UCC method, the parameterized trial function is given by

where is the sum of various excitation levels, e.g.,

denote the single and double excitation levels respectively.

The UCC method possesses all the advantages of the CC method and is also fully variational as well as able to converge when using multi-reference states. As in CC, we truncate the expression for at a given excitation level -- usually single and double excitations leading to the UCCSD ansatz [2].

The Hydrogen molecule

For simplicity, we use the minimal basis set STO-3G for molecule, which includes only the orbital for each atom. Since each atom contributes one spin-orbital, and there are 2 possible spins for each orbital (up or down), this leads to a total of 4 orbitals for in the STO-3G basis set [2], where the subscripts A and B label the atom and label the electron spin respectively.

In the molecular orbital basis for , given by [2] the Slater determinant can be expressed in the occupation number basis as where each .

The second-quantized electronic Hamiltonian in this basis is given by [2]

where

and

where the coefficients are given by Eqs. (5) and (6).

Using the JW encoding, the electronic Hamiltonian for in Eq.(16) can be expressed as a 4-qubit operator [2]

where

and

In the JW encoding, the HF state, which is taken as the reference state for the UCCSD ansatz for VQE, is given by,

which represents the state in which the molecular orbitals and are occupied, while the molecular orbitals are unoccupied. The most general state for with the same charge and spin multiplicity as the HF state can be expressed as [2],

Finally, the UCCSD ansatz for in the STO-3G basis can be simplified to the following single-parameter unitary operator acting on the HF reference state given by Eq. (25) [2]

Implementation details

We use the following procedure to determine the ground-state energy of the molecule at various bond-lengths, i.e., its potential energy surface (PES).

  1. We use OpenFermion-PySCF to compute the coefficients of the different terms of the 4-qubit operator in Eq.(21) representing the electronic Hamiltonian for at the required bond lengths of molecule.
  2. Using Amazon Braket, we implement the UCCSD ansatz given by Eq.(27) through the quantum circuit shown below [2].
  3. We run the above quantum circuit using the local simulator of Amazon Braket for various values of the parameter in the UCCSD ansatz to determine its optimal value and using this value, compute the expectation value of the qubit operator in Eq.(21) to get the estimated ground-state energy of for each value of bond-length.

Finally, we assess the accuracy of the ground-state energy of molecule for various bond-lengths computed by VQE to that computed using the classical chemistry post-HF method FCI (full configuration interaction), which is the most accurate computation that can be performed for a given basis set.

Pre-requisites

Execution

Imports and setup

In [1]:
# create a directory named "data" to store intermediate classical computation results from OpenFermion
!mkdir -p "data"
In [2]:
# import required libraries
import os
import time

import numpy as np
from matplotlib import pyplot as plt
from openfermion import MolecularData
from openfermion.transforms import get_fermion_operator, jordan_wigner
from openfermionpyscf import run_pyscf

from braket.circuits import Circuit, observables
from braket.devices import LocalSimulator
from braket.parametric import FreeParameter

Parameters defining the problem space

In [3]:
# Initialize variable to determine total run-time of the program
run_time = time.time()
# Set parameters that won't change for all simulations
# total charge
tot_chg = 0
# set the multiplicity
# this parameter specifies how electrons are paired in orbitals
# spin multiplicity is equal to the number of unpaired electrons plus one
# e.g., spin multiplicity = 1 implies no unpaired electron, i.e., for every
# spin-up electron in a spatial orbital there is a spin-down electron,
# spin-multiplicity = 3 implies 2 unpaired electrons, and so on.
# See https://en.wikipedia.org/wiki/Multiplicity_(chemistry) for more details
spin_mult = 1
# use the minimal basis set (STO-3G)
basis_set = "sto-3g"
# number of active electrons and orbitals to consider
# For H2 as we're consider all electrons and orbitals as active for STO-3G
occ_ind = act_ind = None
# bond lengths to simulate ground-state of H2 for (in Angstroms)
bond_lengths = np.arange(start=0.24, stop=3.00, step=0.1)
# no. of bond lengths to simulate H2 for
n_configs = len(bond_lengths)
print(f"INFO: Simulating ground-state of H2 molecule for {n_configs} bond lengths")
# no. of VQE parameter values to scan
n_theta = 24
# no. of shots: 0 means exact statevector expectation values (no sampling noise)
n_shots = 0
INFO: Simulating ground-state of H2 molecule for 28 bond lengths

Classical pre-computation of electronic Hamiltonian of

In [4]:
# Dictionary to store molecular data and qubit Hamiltonians for each
# molecular configuration(i.e., bond length)
mol_configs = {}
# Store molecular config data and Hamiltonian for each bond length
for rr in bond_lengths:
    # round to 2 digits to get a reasonable-length number for bond-length
    r = round(rr, 2)
    print(f"INFO: Computing Hamiltonian for bond-length {r} A...")
    geom = [("H", (0.0, 0.0, -r / 2.0)), ("H", (0.0, 0.0, r / 2.0))]
    # Make sure a directory named 'data' exists in the current folder,
    # else this statement will throw an error!
    h2_molecule = MolecularData(
        geometry=geom,
        basis=basis_set,
        multiplicity=spin_mult,
        description="bondlength_" + str(r) + "A",
        filename="",
        data_directory=os.getcwd() + "/data",
    )
    # Run PySCF to get molecular integrals, HF and FCI energies
    h2_molecule = run_pyscf(
        molecule=h2_molecule,
        run_scf=True,
        run_mp2=False,
        run_cisd=False,
        run_ccsd=False,
        run_fci=True,
        verbose=False,
    )
    # Convert electronic Hamiltonian to qubit operator using JW encoding
    h2_qubit_hamiltonian = jordan_wigner(
        get_fermion_operator(
            h2_molecule.get_molecular_hamiltonian(occupied_indices=occ_ind, active_indices=act_ind),
        ),
    )
    # store molecular data and qubit operator for this config in an ordered list
    mol_configs[r] = [h2_molecule, h2_qubit_hamiltonian]
print(f"INFO: Computed Hamiltonians for {len(mol_configs)} bond-lengths.")
INFO: Computing Hamiltonian for bond-length 0.24 A...
INFO: Computing Hamiltonian for bond-length 0.34 A...
INFO: Computing Hamiltonian for bond-length 0.44 A...
INFO: Computing Hamiltonian for bond-length 0.54 A...
INFO: Computing Hamiltonian for bond-length 0.64 A...
INFO: Computing Hamiltonian for bond-length 0.74 A...
INFO: Computing Hamiltonian for bond-length 0.84 A...
INFO: Computing Hamiltonian for bond-length 0.94 A...
INFO: Computing Hamiltonian for bond-length 1.04 A...
INFO: Computing Hamiltonian for bond-length 1.14 A...
INFO: Computing Hamiltonian for bond-length 1.24 A...
INFO: Computing Hamiltonian for bond-length 1.34 A...
INFO: Computing Hamiltonian for bond-length 1.44 A...
INFO: Computing Hamiltonian for bond-length 1.54 A...
INFO: Computing Hamiltonian for bond-length 1.64 A...
INFO: Computing Hamiltonian for bond-length 1.74 A...
INFO: Computing Hamiltonian for bond-length 1.84 A...
INFO: Computing Hamiltonian for bond-length 1.94 A...
INFO: Computing Hamiltonian for bond-length 2.04 A...
INFO: Computing Hamiltonian for bond-length 2.14 A...
INFO: Computing Hamiltonian for bond-length 2.24 A...
INFO: Computing Hamiltonian for bond-length 2.34 A...
INFO: Computing Hamiltonian for bond-length 2.44 A...
INFO: Computing Hamiltonian for bond-length 2.54 A...
INFO: Computing Hamiltonian for bond-length 2.64 A...
INFO: Computing Hamiltonian for bond-length 2.74 A...
INFO: Computing Hamiltonian for bond-length 2.84 A...
INFO: Computing Hamiltonian for bond-length 2.94 A...
INFO: Computed Hamiltonians for 28 bond-lengths.

Construction of UCCSD ansatz circuit in Braket

In [5]:
# Construct circuit for UCCSD ansatz parameterized by VQE parameter per McArdle et al.
a_theta = FreeParameter("a_theta")
# Initialize HF state |0011>
ansatz_uccsd = Circuit().x(2).x(3)
# Perform initial rotations to measure in Y & X bases
ansatz_uccsd.rx(3, np.pi / 2.0).h(range(3))
# Entangle with CNOTs
ansatz_uccsd.cnot(3, 2).cnot(2, 1).cnot(1, 0)
# Perform the rotation in Z-basis
ansatz_uccsd.rz(0, a_theta)
# Uncompute the rotations
ansatz_uccsd.cnot(1, 0).cnot(2, 1).cnot(3, 2)
ansatz_uccsd.h(range(3))
ansatz_uccsd.rx(3, -np.pi / 2.0)

# initialize quantum device to run VQE over
local_sim = LocalSimulator()
# verify by running the circuit with no rotation and verifying we get HF state
print(ansatz_uccsd)
n_qubits = ansatz_uccsd.qubit_count
print(f"Total number of qubits in the circuit: {n_qubits}")
# We can fix the value of a_theta by calling the circuit with the value filled as follows.
# print(local_sim.run(ansatz_uccsd(0)).result().state_vector)
print(local_sim.run(Circuit().add(ansatz_uccsd(0)).state_vector(), shots=n_shots).result().values[0])
# We can also fix the value of a_theta by supplying the inputs argument to run
print(
    local_sim.run(Circuit().add(ansatz_uccsd).state_vector(), shots=n_shots, inputs={"a_theta": 0.0})
    .result()
    .values[0],
)
T  : │  0  │     1      │  2  │  3  │  4  │       5       │  6  │  7  │  8  │      9      │
      ┌───┐                          ┌───┐ ┌─────────────┐ ┌───┐ ┌───┐                     
q0 : ─┤ H ├──────────────────────────┤ X ├─┤ Rz(a_theta) ├─┤ X ├─┤ H ├─────────────────────
      └───┘                          └─┬─┘ └─────────────┘ └─┬─┘ └───┘                     
      ┌───┐                    ┌───┐   │                     │   ┌───┐ ┌───┐               
q1 : ─┤ H ├────────────────────┤ X ├───●─────────────────────●───┤ X ├─┤ H ├───────────────
      └───┘                    └─┬─┘                             └─┬─┘ └───┘               
      ┌───┐    ┌───┐     ┌───┐   │                                 │   ┌───┐     ┌───┐     
q2 : ─┤ X ├────┤ H ├─────┤ X ├───●─────────────────────────────────●───┤ X ├─────┤ H ├─────
      └───┘    └───┘     └─┬─┘                                         └─┬─┘     └───┘     
      ┌───┐ ┌──────────┐   │                                             │   ┌───────────┐ 
q3 : ─┤ X ├─┤ Rx(1.57) ├───●─────────────────────────────────────────────●───┤ Rx(-1.57) ├─
      └───┘ └──────────┘                                                     └───────────┘ 
T  : │  0  │     1      │  2  │  3  │  4  │       5       │  6  │  7  │  8  │      9      │

Unassigned parameters: [a_theta].
Total number of qubits in the circuit: 4
{'0011': 1.0}
{'0011': 1.0}

Computation of expectation value of Hamiltonian operator for

In [6]:
def _build_observable(indices_gates):
    """Convert OpenFermion term to a Braket observable."""
    obs_map = {"X": observables.X, "Y": observables.Y, "Z": observables.Z}
    factors = [
        obs_map[gate](n_qubits - 1 - ind) for ind, gate in indices_gates
    ]
    return observables.TensorProduct(factors) if len(factors) > 1 else factors[0]


def H_exp(a_qH, a_ckt, a_dev, a_shots=n_shots):
    """Get expectation value of Hamiltonian for a given circuit result.

    Batches all non-identity Pauli terms into a single circuit run,
    so the statevector is computed once and all observables are evaluated against it.

    Note: This implementation adds multiple observables to a single circuit, which
    works for simulators. For QPU execution, non-commuting terms would need to be
    measured in separate circuit runs.

    Parameters
    ----------
        a_qH [OpenFermion QubitHamiltonian.terms]: Dictionary of OpenFermion QubitHamiltonian operator terms
        a_ckt [Braket Circuit]: Circuit to create the final state
        a_dev [Braket Device]: Quantum device to run a_ckt on
        a_shots [int]: No. of shots (0 for exact statevector expectation values)
    Returns:
        H_e [float]: Expectation value of a_qH for a_ket

    """
    H_e = 0.0
    measuring_ckt = Circuit().add(a_ckt)
    coeffs = []
    for term in a_qH:
        coeff = np.real(a_qH[term])
        if not term:
            # identity term contributes coeff * 1
            H_e += coeff
        else:
            measuring_ckt.expectation(observable=_build_observable(term))
            coeffs.append(coeff)
    # Single simulator run for all non-identity terms
    result = a_dev.run(measuring_ckt, shots=a_shots).result()
    for coeff, val in zip(coeffs, result.values):
        H_e += coeff * val
    return H_e

Results

In [7]:
# Loop over all bond lengths
for r in mol_configs:
    print(f"INFO: Computing ground-state energy for bond-length {r} A...")
    # initialize min_energy for this config
    mol_configs[r].append(np.inf)
    # Loop over all VQE parameter values
    for theta in np.linspace(start=-np.pi, stop=np.pi, num=n_theta, endpoint=False):
        # get expectation value of this config's Hamiltonian for this parameter value
        exp_H_theta = H_exp(mol_configs[r][1].terms, ansatz_uccsd(theta), local_sim)
        # if this expectation value is less than min found so far, update it
        mol_configs[r][2] = min(exp_H_theta, mol_configs[r][2])
    print(f"min <H(R={r} A)> = {mol_configs[r][2]:.4f} Ha")
INFO: Computing ground-state energy for bond-length 0.24 A...
min <H(R=0.24 A)> = -0.2294 Ha
INFO: Computing ground-state energy for bond-length 0.34 A...
min <H(R=0.34 A)> = -0.7494 Ha
INFO: Computing ground-state energy for bond-length 0.44 A...
min <H(R=0.44 A)> = -0.9727 Ha
INFO: Computing ground-state energy for bond-length 0.54 A...
min <H(R=0.54 A)> = -1.0785 Ha
INFO: Computing ground-state energy for bond-length 0.64 A...
min <H(R=0.64 A)> = -1.1277 Ha
INFO: Computing ground-state energy for bond-length 0.74 A...
min <H(R=0.74 A)> = -1.1363 Ha
INFO: Computing ground-state energy for bond-length 0.84 A...
min <H(R=0.84 A)> = -1.1249 Ha
INFO: Computing ground-state energy for bond-length 0.94 A...
min <H(R=0.94 A)> = -1.1123 Ha
INFO: Computing ground-state energy for bond-length 1.04 A...
min <H(R=1.04 A)> = -1.0907 Ha
INFO: Computing ground-state energy for bond-length 1.14 A...
min <H(R=1.14 A)> = -1.0664 Ha
INFO: Computing ground-state energy for bond-length 1.24 A...
min <H(R=1.24 A)> = -1.0481 Ha
INFO: Computing ground-state energy for bond-length 1.34 A...
min <H(R=1.34 A)> = -1.0229 Ha
INFO: Computing ground-state energy for bond-length 1.44 A...
min <H(R=1.44 A)> = -1.0024 Ha
INFO: Computing ground-state energy for bond-length 1.54 A...
min <H(R=1.54 A)> = -0.9943 Ha
INFO: Computing ground-state energy for bond-length 1.64 A...
min <H(R=1.64 A)> = -0.9809 Ha
INFO: Computing ground-state energy for bond-length 1.74 A...
min <H(R=1.74 A)> = -0.9646 Ha
INFO: Computing ground-state energy for bond-length 1.84 A...
min <H(R=1.84 A)> = -0.9565 Ha
INFO: Computing ground-state energy for bond-length 1.94 A...
min <H(R=1.94 A)> = -0.9517 Ha
INFO: Computing ground-state energy for bond-length 2.04 A...
min <H(R=2.04 A)> = -0.9458 Ha
INFO: Computing ground-state energy for bond-length 2.14 A...
min <H(R=2.14 A)> = -0.9423 Ha
INFO: Computing ground-state energy for bond-length 2.24 A...
min <H(R=2.24 A)> = -0.9418 Ha
INFO: Computing ground-state energy for bond-length 2.34 A...
min <H(R=2.34 A)> = -0.9351 Ha
INFO: Computing ground-state energy for bond-length 2.44 A...
min <H(R=2.44 A)> = -0.9325 Ha
INFO: Computing ground-state energy for bond-length 2.54 A...
min <H(R=2.54 A)> = -0.9341 Ha
INFO: Computing ground-state energy for bond-length 2.64 A...
min <H(R=2.64 A)> = -0.9352 Ha
INFO: Computing ground-state energy for bond-length 2.74 A...
min <H(R=2.74 A)> = -0.9335 Ha
INFO: Computing ground-state energy for bond-length 2.84 A...
min <H(R=2.84 A)> = -0.9352 Ha
INFO: Computing ground-state energy for bond-length 2.94 A...
min <H(R=2.94 A)> = -0.9330 Ha
In [8]:
# Plot ground-state energy for each configuration vs bond length
plt.figure(figsize=(8, 6), dpi=700)
plt.plot(list(mol_configs.keys()), [val[0].hf_energy for val in mol_configs.values()], label="HF")
plt.plot(list(mol_configs.keys()), [val[0].fci_energy for val in mol_configs.values()], label="FCI")
plt.plot(list(mol_configs.keys()), [val[2] for val in mol_configs.values()], "x-", label="VQE")
plt.grid()
plt.xlabel("Bond length of H2 [A]")
plt.ylabel("Ground-state energy for H2 [Ha]")
plt.legend()
plt.title("VQE computed ground-state energy of H2 vs bond-length for STO-3G basis vs HF and FCI")
plt.savefig("H2_PES_byVQE.png")
run_time = time.time() - run_time
print(f"Total running time: {run_time:.2f} s")
Total running time: 123.00 s

Discussion

In the plot of the computed ground-state energy of the molecule against its bond length above, the curve labeled "HF" denotes the ground-state energy computed by using the classical Hartree-Fock method, i.e., classical pre-computation alone. The curve labeled "FCI" denotes the ground-state energy of for each bond-length computed using one of the most accurate classical post-Hartree-Fock method, viz., Full Configuration Interaction (FCI). As can be seen from the curve labeled "VQE" in the plot above, the computational results of the quantum computational method VQE agree extremely well with the FCI results over the entire range of bond-lengths simulated for the molecule. This shows that the quantum computational VQE method can be very competitive with the most accurate classical computational chemistry methods.

References

[1] Helgaker, T., Jorgensen, P., & Olsen, J. (2014). Molecular electronic-structure theory. John Wiley & Sons.

[2] McArdle, S., Endo, S., Aspuru-Guzik, A., Benjamin, S., & Yuan, X. (2020). Quantum computational chemistry. Reviews of Modern Physics, 92(1).

[3] Cao, Y., Romero J., Olson, J. P., Degroote, M., Johnson, P. D., Kieferov, M., Kivlichan, I. D., Menke, T., Peropadre, B., Sawaya, N. P. D., Sim, S., Veis, L., & Aspuru-Guzik A. (2018). Quantum chemistry in the age of quantum computing. Chemical Reviews, 119(19), 10856–10915.

[4] Hempel, C., Maier, C., Romero, J., McClean, J., Monz, T., Shen, H., Jurcevic, P., Lanyon, B. P., Love, P., Babbush, R., Aspuru-Guzik, A., Blatt, R., & Roos C. F. (2018). Quantum Chemistry Calculations on a Trapped-Ion Quantum Simulator. Phys.Rev. X, 8(3), 031022.

[5] McClean, J. R., Sung, K. J., Kivlichan, I. D., Bonet-Monroig, X., Cao, Y., Dai, C., Fried, E. S., Gidney, C., Gimby, B., Gokhale, P., Häner, T., Hardikar, T., Havlíček, V., Higgott, O., Huang, C., Izaac, J., Jiang, Z., Kirby, W., Liu, X., ..., Babbush, R. (2017). OpenFermion: The electronic structure package for quantum computers. arXiv:1710.07629.

[6] Sun, Q., Berkelbach, T. C., Blunt, N. S., Booth, G. H., Guo, S., Li, Z., Liu, J., McClain, J., Sayfutyarova, E. R., Sharma, S., Wouters, S., & Chan, G. K.-L. (2017). The Python-based simulations of chemistry framework (PySCF). WIREs Compututational Molecular Science, 8(e1340).

[7] Sun. Q. (2015). Libcint: An efficient general integral library for Gaussian basis functions. J. Comp. Chem. 36(1664).

Join the Discussion

Comments (0)

No comments yet. Be the first to share your thoughts!

Indexed by QCR Librarian

This entry was created automatically from publicly available records. QCR links to public sources and only stores repository content where the license permits redistribution.

Versions

v1 Latest
Jun 16, 2026
qcr:2606.24663.1

Cite all versions? Use the base QCR ID to always reference the latest version of this entry.

Tools used

Amazon Braket SDK

Keywords

vqe
quantum-chemistry
hydrogen
variational
braket

You may also like5