Getting started with Variational Quantum Eigensolving¶
Here, we show how to find a variational ground state to the following Hamiltonian:
$$ H = \vec{\sigma}_1\cdot \vec{\sigma}_2 = \sigma^X_1 \sigma^X_2 + \sigma^Y_1 \sigma^Y_2 + \sigma^Z_1 \sigma^Z_2 $$
We start by defining the Hamiltonian (in the form of an observable), and choose a variational circuit with two parameters:
In [1]:
from qat.core import Observable, Term
from qat.lang.AQASM import Program, CNOT, H, RX, RY, RZ
H_XY = Observable(2,
pauli_terms=[Term(1., "XX", [0, 1]),
Term(1., "YY", [0, 1]),
Term(1., "ZZ", [0, 1])]
)
print("Hamiltonian:", H_XY)
prog = Program()
qbits = prog.qalloc(2)
alpha = prog.new_var(float, "\\alpha")
beta = prog.new_var(float, "\\beta")
gamma = prog.new_var(float, "\\gamma")
prog.apply(H, qbits[0])
prog.apply(RY(alpha), qbits[1])
prog.apply(CNOT, qbits)
prog.apply(RX(beta), qbits[0])
prog.apply(RY(gamma), qbits[1])
circuit = prog.to_circ()
circuit.display()
Hamiltonian: 1.0 * (XX|[0, 1]) + 1.0 * (YY|[0, 1]) + 1.0 * (ZZ|[0, 1])
Optimization¶
We now perform the optimization, using a Variational Plugin:
In [2]:
from qat.plugins import ScipyMinimizePlugin
from qat.qpus import LinAlg
linalg_qpu = LinAlg()
theta0 = [0.4, -0.3, 0.6]
optimizer_scipy = ScipyMinimizePlugin(method="COBYLA",
x0=theta0,
tol=1e-3,
options={"maxiter": 2000})
qpu = optimizer_scipy | linalg_qpu
job = circuit.to_job(job_type="OBS", observable=H_XY)
result = qpu.submit(job)
print("Minimum energy =", result.value)
print("Optimal angles =", result.meta_data["parameters"])
#print("==========Optimization data=============\n", result.meta_data['optimization_trace'])
%matplotlib inline
import matplotlib.pyplot as plt
plt.plot(eval(result.meta_data['optimization_trace']))
plt.xlabel("Steps")
plt.ylabel("Energy");
Minimum energy = -2.999999985437741 Optimal angles = [np.float64(-0.00010707754003805325), np.float64(-4.10250986041513e-05), np.float64(3.1415550557015255)]
True ground state¶
In this simple case, we can compute the ground state energy by diagonalizing the matrix corresponding to the Hamiltonian:
In [3]:
import numpy as np
from qat.fermion import SpinHamiltonian
H_XY_spin = SpinHamiltonian(nqbits=H_XY.nbqbits, terms=H_XY.terms)
H_XY_matrix = H_XY_spin.get_matrix()
eigvals, eigvecs = np.linalg.eigh(H_XY_matrix)
print("Exact ground state energy: ", min(eigvals))
Exact ground state energy: -3.0
Going further:¶
- play with the Hamiltonian
- play with the ansatz
- play with the QPU: try with a noisy QPU
- play with the optimizer (change the method)