Variational Quantum Eigensolver

Variational Quantum Eigensolver [1] (VQE) with Transverse Field Ising Model Hamiltonian using TensorLy-Quantum. TensorLy-Quantum provides a TT-tensor network circuit simulator for large-scale simulation of variational quantum circuits in a Pythonic/PyTorchian interface with full Autograd support similar to traditional PyTorch Neural Networks.

import tensorly as tl
import tlquantum as tlq
from tensorly.tt_matrix import TTMatrix
from torch import randint, rand, arange
from torch.optim import Adam
import matplotlib.pyplot as plt
#device = 'cuda' # Use GPU
device = 'cpu' # Use CPU

nepochs = 80 #number of training epochs

nqubits = 5 #number of qubits
ncontraq = 2 #2 #number of qubits to pre-contract into single core
ncontral = 2 #2 #number of layers to pre-contract into a single core
nterms = 10
lr = 0.5
state = tlq.spins_to_tt_state([0 for i in range(nqubits)], device) # generate generic zero state |00000>
state = tlq.qubits_contract(state, ncontraq)

two-qubit terms

qubits1 = randint(nqubits, (nterms,), device=device) # randomly generated first qubits of each two-qubit term
qubits2 = randint(nqubits, (nterms,), device=device) # randomly generated second qubits of each two-qubit term
qubits2[qubits2==qubits1] += 1 # because qubits in this Hamiltonian randomly generated, eliminate self-interacting terms
qubits2[qubits2 >= nqubits] = 0
weights = rand((nterms,), device=device) # randomly generated coefficients of each two-qubit interaction in Hamiltonian
binary_H = tlq.binary_hamiltonian(tlq.pauli_z(device), nqubits, qubits1, qubits2, weights) # build the spin-spin Hamiltonian H
qubits = arange(nqubits, device=device) # specify that each qubit will have a transverse field term
weights = rand((nqubits,), device=device) # randomly generated coefficients for the transverse field felt by each qubit
unary_H = tlq.unary_hamiltonian(tlq.pauli_x(device), nqubits, qubits, weights) #build the transverse field Hamiltonian
Ising_H = tlq.tt_matrix_sum(binary_H, unary_H)
custom_U = tlq.Unitary([tlq.RotY(device), *tlq.so4(0,1, device), tlq.RotY(device), *tlq.so4(2, 3, device)], nqubits, ncontraq)
RotY = tlq.UnaryGatesUnitary(nqubits, ncontraq, device=device) # one Y-axis rotation gate applied to each qubit of the circuit
parity = 0
CZ0 = tlq.BinaryGatesUnitary(nqubits, ncontraq, tlq.cz(device=device), parity) # one controlled-z gate for each pair of qubits using even parity (even qubits control)
parity = 1
SO4_01 = tlq.BinaryGatesUnitary(nqubits, ncontraq, tlq.so4(2,3, device=device), parity) # one SO4 rotation about two-qubit states |2> and |3> with odd parity
unitaries = [RotY, SO4_01, tlq.UnaryGatesUnitary(nqubits, ncontraq, device=device), CZ0]
repeat_block, unitaries_automatic = 3, []
for i in range(repeat_block):
    unitaries_automatic += unitaries
circuit = tlq.TTCircuit(unitaries, ncontraq, ncontral)
opt = Adam(circuit.parameters(), lr=lr, amsgrad=True) # define PyTorch optimizer
energy_vec = tl.zeros(nepochs)

for epoch in range(nepochs):
    # TTCircuit forward pass computes expectation value of Ising_H
    energy = circuit.forward_expectation_value(state, Ising_H)
    print('Energy (loss) at epoch ' + str(epoch) + ' is ' + str(energy[0].item()) + '. \n')

    # PyTorch Autograd attends to backwards pass and parameter update
    energy.backward()
    opt.step()
    opt.zero_grad(epoch)
    energy_vec[epoch] = energy


Ising_H = TTMatrix(Ising_H).to_matrix()
true_energies, _ = tl.eigh(Ising_H)
ground_state_energy = true_energies[0]
plt.figure()
plt.plot(energy_vec.detach().numpy(), color='r', linewidth=5)
plt.hlines(ground_state_energy, 0, nepochs, color='k', linewidth=5, linestyle='--')
plt.xlabel('Epochs', fontsize=20)
plt.ylabel('Energy', fontsize=20)
plt.xticks(fontsize=20)
plt.yticks(fontsize=20)
plt.legend(['Variational Solution', 'Ground Truth'], fontsize=20)
plt.show()
plot vqe transverse field Ising

Out:

Energy (loss) at epoch 0 is 1.3870817422866821.

Energy (loss) at epoch 1 is 0.25226911902427673.

Energy (loss) at epoch 2 is 0.2505115866661072.

Energy (loss) at epoch 3 is -0.48984140157699585.

Energy (loss) at epoch 4 is -1.4349086284637451.

Energy (loss) at epoch 5 is -2.225308418273926.

Energy (loss) at epoch 6 is -2.671506643295288.

Energy (loss) at epoch 7 is -2.9844253063201904.

Energy (loss) at epoch 8 is -3.786001205444336.

Energy (loss) at epoch 9 is -4.507091045379639.

Energy (loss) at epoch 10 is -4.780369758605957.

Energy (loss) at epoch 11 is -4.630244255065918.

Energy (loss) at epoch 12 is -4.350880146026611.

Energy (loss) at epoch 13 is -4.168337821960449.

Energy (loss) at epoch 14 is -4.178856372833252.

Energy (loss) at epoch 15 is -4.323515892028809.

Energy (loss) at epoch 16 is -4.464426040649414.

Energy (loss) at epoch 17 is -4.597195625305176.

Energy (loss) at epoch 18 is -4.791545391082764.

Energy (loss) at epoch 19 is -4.992600917816162.

Energy (loss) at epoch 20 is -5.040241241455078.

Energy (loss) at epoch 21 is -4.940978050231934.

Energy (loss) at epoch 22 is -4.83993673324585.

Energy (loss) at epoch 23 is -4.781282424926758.

Energy (loss) at epoch 24 is -4.764399528503418.

Energy (loss) at epoch 25 is -4.8129119873046875.

Energy (loss) at epoch 26 is -4.89941930770874.

Energy (loss) at epoch 27 is -4.975061416625977.

Energy (loss) at epoch 28 is -5.018291473388672.

Energy (loss) at epoch 29 is -5.037726402282715.

Energy (loss) at epoch 30 is -5.047263145446777.

Energy (loss) at epoch 31 is -5.05147647857666.

Energy (loss) at epoch 32 is -5.037568092346191.

Energy (loss) at epoch 33 is -5.006039619445801.

Energy (loss) at epoch 34 is -4.994319438934326.

Energy (loss) at epoch 35 is -5.017548561096191.

Energy (loss) at epoch 36 is -5.0392351150512695.

Energy (loss) at epoch 37 is -5.039334297180176.

Energy (loss) at epoch 38 is -5.047135353088379.

Energy (loss) at epoch 39 is -5.067873954772949.

Energy (loss) at epoch 40 is -5.07968807220459.

Energy (loss) at epoch 41 is -5.081919193267822.

Energy (loss) at epoch 42 is -5.0813093185424805.

Energy (loss) at epoch 43 is -5.08251953125.

Energy (loss) at epoch 44 is -5.088953018188477.

Energy (loss) at epoch 45 is -5.092121124267578.

Energy (loss) at epoch 46 is -5.085857391357422.

Energy (loss) at epoch 47 is -5.085341453552246.

Energy (loss) at epoch 48 is -5.093048095703125.

Energy (loss) at epoch 49 is -5.093312740325928.

Energy (loss) at epoch 50 is -5.087295055389404.

Energy (loss) at epoch 51 is -5.088972568511963.

Energy (loss) at epoch 52 is -5.093959331512451.

Energy (loss) at epoch 53 is -5.0924458503723145.

Energy (loss) at epoch 54 is -5.08867883682251.

Energy (loss) at epoch 55 is -5.090641021728516.

Energy (loss) at epoch 56 is -5.093991756439209.

Energy (loss) at epoch 57 is -5.0917840003967285.

Energy (loss) at epoch 58 is -5.089733600616455.

Energy (loss) at epoch 59 is -5.09297513961792.

Energy (loss) at epoch 60 is -5.094057083129883.

Energy (loss) at epoch 61 is -5.091882705688477.

Energy (loss) at epoch 62 is -5.0927557945251465.

Energy (loss) at epoch 63 is -5.094701766967773.

Energy (loss) at epoch 64 is -5.0941996574401855.

Energy (loss) at epoch 65 is -5.094005107879639.

Energy (loss) at epoch 66 is -5.09486198425293.

Energy (loss) at epoch 67 is -5.095386505126953.

Energy (loss) at epoch 68 is -5.095376014709473.

Energy (loss) at epoch 69 is -5.095390319824219.

Energy (loss) at epoch 70 is -5.095790863037109.

Energy (loss) at epoch 71 is -5.096087455749512.

Energy (loss) at epoch 72 is -5.09603214263916.

Energy (loss) at epoch 73 is -5.096078872680664.

Energy (loss) at epoch 74 is -5.0962629318237305.

Energy (loss) at epoch 75 is -5.09645938873291.

Energy (loss) at epoch 76 is -5.096410751342773.

Energy (loss) at epoch 77 is -5.096309661865234.

Energy (loss) at epoch 78 is -5.0966291427612305.

Energy (loss) at epoch 79 is -5.096649169921875.

Total running time of the script: ( 0 minutes 0.774 seconds)

Gallery generated by Sphinx-Gallery