Simple implementation of the UCC ansatz for computing the ground state of the H2
molecule. The Hamiltonian coefficients are taken from the following paper:
https://arxiv.org/pdf/1512.06860.pdf.
Simple 2 qubits unitary coupled cluster ansatz for H2 molecule
Let's define the Hamiltonian of the problem in the following form: hamilt =
[list of coefficients, list of Pauli operators, list of qubits]. For example:
hamilt=[[3,4],[[X,X],[Y]],[[0,1],[3]]].
In the following function we generate the Hamiltonian with the format above.
fromtypingimportIterablefromqadenceimportX,Y,Z,I,adddefmake_hamiltonian(hamilt:Iterable,nqubits:int):nb_terms=len(hamilt[0])blocks=[]foriterinrange(nb_terms):block=kron(gate(qubit)forgate,qubitinzip(hamilt[1][iter],hamilt[2][iter]))blocks.append(hamilt[0][iter]*block)returnadd(*blocks)nqbits=2# Hamiltonian definition using the convention outlined abovehamilt_R07=[[0.2976,0.3593,-0.4826,0.5818,0.0896,0.0896],[[I,I],[Z],[Z],[Z,Z],[X,X],[Y,Y]],[[0,1],[0],[1],[0,1],[0,1],[0,1]]]hamiltonian=make_hamiltonian(hamilt_R07,nqbits)
Let's now create a QuantumCircuit representing the variational ansatz and plug
it into a QuantumModel instance. From there, it is very easy to compute the
energy by simply evaluating the expectation value of the Hamiltonian operator.
Let's now resent the parameters and set them randomly before starting the optimization loop.
init_params=torch.rand(model.num_vparams)model.reset_vparams(init_params)n_epochs=100lr=0.05optimizer=torch.optim.Adam(model.parameters(),lr=lr)foriinrange(n_epochs):optimizer.zero_grad()out=model.expectation({})out.backward()optimizer.step()print("Ground state energy =",out.item(),"Hatree")
Groundstateenergy=-1.1449597119944634Hatree
Unrestricted Hamiltonian
This result is in line with what obtained in the reference paper. Let's now
perform the same calculations but with a standard hardware efficient ansatz
(i.e. not specifically tailored for the H2 molecule) and with an unrestricted
Hamiltonian on 4 qubits. The values of the coefficients are taken from BK Hamiltonian, page 28[^2].
model=QuantumModel(ansatz_bis,observable=Hamiltonian_bis,backend="pyqtorch",diff_mode="ad")values={}out=model.expectation(values)# initialize some random initial parametersinit_params=torch.rand(model.num_vparams)model.reset_vparams(init_params)n_epochs=100lr=0.05optimizer=torch.optim.Adam(model.parameters(),lr=lr)foriinrange(n_epochs):optimizer.zero_grad()out=model.expectation(values)out.backward()optimizer.step()if(i+1)%10==0:print(f"Epoch {i+1} - Loss: {out.item()}")print("Ground state energy =",out.item(),"a.u")
In a.u, the final ground state energy is a bit higher the expected -1.851 a.u
(see page 33 of the reference paper mentioned above). Increasing the ansatz
depth is enough to reach the desired accuracy.
References
Seeley et al. - The Bravyi-Kitaev transformation for quantum computation of electronic structure ↩