Amazon Braket: Solving the Transverse Ising Model with VQE

In this tutorial we show how to solve for the ground state of the Transverse Ising Model, arguably one of the most prominent, canonical quantum spin systems, using the variational quantum eigenvalue solver (VQE). The VQE algorithm belongs to the class of hybrid quantum algorithms (leveraging both classical as well as quantum compute), that are widely believed to be the working horse for the current NISQ (noisy intermediate-scale quantum) era. To validate our approach we benchmark our results with exact results as obtained from a Jordan-Wigner transformation.
We provide a step-by-step walkthrough explaining the VQE quantum algorithm and show how to build the corresponding parametrized quantum circuit ansatz using the Braket SDK, with simple modular building blocks (that can be re-used for other purposes). While we demonstrate our proof-of-concept approach using classical simulators for circuit execution, our code could in principle be run on actual quantum hardware by simply changing the definition of the device object.
Background: The Variational Quantum Eigensolver (VQE)
Quantum computers hold the promise to outperform even the most-powerful classical computers on a range of computational problems in (for example) optimization, chemistry, material science and cryptography. The canonical set of quantum algorithms (such as Shor's or Grover's quantum algorithms), however, comes with hardware requirements (such as a large number of quantum gates) that are currently not available with state-of-the-art technology. Specifically, these algorithms are typically believed to be feasible only with fault-tolerance as provided by quantum error correction. In the current noisy intermediate-sclae (NISQ) era, near-term quantum computers do not have a large enough number of physical qubits for the implementation of error correction protocols, making this canonical set of quantum algorithms unsuitable for near-term devices. Against this background, the near-term focus has widely shifted to the class of hybrid quantum algorithms that do not require quantum error correction. In these hybrid quantum algorithms are the noisy near-term quantum computers are used as co-processors only, within a larger classical optimization loop, as sketched in the schematic figure below. Here, the undesired effects of noise are suppressed by deliberately limiting the quantum circuits on the quantum processing unit (QPU) to short bursts of the calculation, and the need for long coherence times (as required for the standard set of quantum algorithms) is traded for a classical overhead due to (possibly many) measurement repetitions and (essentially error-free) classical processing.
Background: The Transverse Ising Model
Illustration of the VQE ansatz
Here, denotes the (true) lowest energy eigenvalue of the Hamiltonian . Since (for sufficiently large systems with more than ∼50 qubits) classical computers are unable to efficiently prepare, store and measure the wavefunction, we use the quantum computer for this subroutine. We then use the classical computer to iteratively update the parameters using some optimization algorithm.
VQE Simulation on a Local Simulator
# set up the problem
SHOTS = 1000
N = 10 # number of qubits
n_initial = 30 # number of random seeds to explore optimization landscape
verbose = False # control amount of print output
# set counters
CYCLE = 0
# set up Ising matrix with nearest neighbour interactions and PBC
J = get_ising_interactions(N)
# set options for classical optimization
if verbose:
options = {'disp': True}
else:
options = {}
# kick off training
start = time.time()
# parameter scan
stepsize = 0.5
xvalues = np.arange(0, 2+stepsize, stepsize)
results = []
results_site = []
for bb in xvalues:
b_field = bb
print('Strength of magnetic field:', b_field)
energy_min = train(b_field, options=options, n_qubits=N, n_shots=SHOTS, n_initial=n_initial,
s3_folder=s3_folder, verbose=verbose)
results.append(energy_min)
results_site.append(energy_min/N)
# reset counters
CYCLE = 0
end = time.time()
# print execution time
print('Code execution time [sec]:', end - start)
# print optimized results
print('Optimal energies:', results)
print('Optimal energies (per site):', results_site)