Adam optimizer doesn't work with qiskit.aer

Hello,

The code below is based on this paper : https://arxiv.org/pdf/2011.10395.pdf
and it is used to solve non linear DEs.

When I ran the code on the default.qubit , everything works fine (although a bit slow). I then moved it to qiskit.aer, and it get stucks when calculating the gradient. I’m not sure why, but everything else works, i.e. it gets the expectation values and calculate the loss, but then gets stuck, no error message.

I need this to work with qiskit, because I eventually have to run this code on a Hardware.

import qiskit
from qiskit import *
import pennylane as qml
from pennylane import numpy as np
from numpy import pi
from pennylane.optimize import AdamOptimizer
from pennylane.optimize import AdagradOptimizer

import matplotlib.pyplot as plt
import time

dev = qml.device('qiskit.aer', wires=6)
num_layers = 5
bound = 1
div=1
var_init = np.random.uniform(0, np.pi * 2, (3*num_layers, 6))

#this is the ansatz
def layers(var,n_wires,d):
    for i in range(n_wires):
        qml.RZ(var[0+d*3][i],wires=i)
        qml.RX(var[1+d*3][i],wires=i)
        qml.RZ(var[2+d*3][i],wires=i)
    for i in range(n_wires):
        if i !=n_wires-1:
            qml.CNOT(wires=[i, i+1])
#this is the first quantum circuit
    @qml.qnode(dev)
def qfc(var, x,n_wires,depth):
    for i in range(n_wires):
        qml.RY(x, wires=i)

    # "layer" subcircuits
    for d in range(depth):
        layers(var,n_wires,d)

    return [qml.expval(qml.PauliZ(i)) for i in range(n_wires)]

#second quantum circuit
@qml.qnode(dev)
def dqcplus(var,x,n_wires,depth,num):
    #print(var)
    for i in range(n_wires):
        if i != num:
            qml.RY(x,wires=i)
        else:
            qml.RY(x+pi/2,wires=i)
    for d in range(depth):
        layers(var,n_wires,d)

    return [qml.expval(qml.PauliZ(i)) for i in range(n_wires)]

@qml.qnode(dev)
def dqcmin(var,x,n_wires,depth,num):
    for i in range(n_wires):
        if i != num:
            qml.RY(x,wires=i)
        else:
            qml.RY(x-pi/2,wires=i)
    for d in range(depth):
        layers(var,n_wires,d)

    return [qml.expval(qml.PauliZ(i)) for i in range(n_wires)]

Don’t worry too much about the second circuits, they are essentially like the first one, but with shifted angles for the gates.

we then have our loss and cost function.

    def loss(preds):
        loss = 0
        for p in preds:
            loss += p**2
        loss = loss/len(preds)
        print("loss calculated")
        return loss

def cost(var,points,fb):
    preds=[]
    
    for x in points:
        cplus = [sum(dqcplus(var = var,x=2*np.arccos(x),n_wires=6,depth=num_layers,num=i))/div for i in range(6)]
        cmin = [sum(dqcmin(var = var,x=2*np.arccos(x),n_wires=6,depth=num_layers,num=i))/div for i in range(6)]
        
        du = (1/2)*(-2/np.sqrt(1-x**2))*(sum(cplus)-sum(cmin))
        
        u=fb+sum(qfc(var = var,x=2*np.arccos(x),n_wires=6,depth=num_layers))/div
       
        pred = du+(8*u*(0.1+np.tan(8*x)))
        
        preds.append(pred)
    
    return loss(preds)

and finally, the part where it all goes wrong, the optimization step

opt = AdamOptimizer(0.01, beta1=0.9, beta2=0.99)
var = var_init
coste = []
start = time.time()
print("starting")
for it in range(10):
    fb = bound-sum(qfc(var = var,x=2*np.arccos(0),n_wires=6,depth=num_layers))/div
var, _cost = opt.step_and_cost(lambda v:cost(v, np.linspace(0, 0.9, 10),float(fb)),var)
    print("success")
    coste.append(_cost)
    print("Iter: {:5d} | Cost: {:0.7f} ".format(it, _cost))
    #if _cost <0.1:
     #   break
end = time.time()
print("the optimisation is finished, it took")
print(end - start)  

Sorry about all the indenting, I’m new to posting on help blog.

So to resume, this code works fine if I use the default.qubit backend. But when I move to qiskit.aer, it fails to calculate the gradient, but it can still evaluate the quantul circuit.

I hope I am just missing something small ? I do know that I have a lot of parameter to optimize, I think its something like 156+ 15662 =1170. But actually its more like 90 since the parameter in the second circuit are the same as the first. But again, it works fine with the default.qubit so I’m quite loss.

Thanks for any help guys :slight_smile:

Hi @Julien_Bruyninckx, welcome to the Forum!

I can see that there is a big slowdown with running your program using qiskit.aer compared to default.qubit. This is not specific to the Adam optimizer, since you get a similar slowdown with the GradientDescentOptimizer. It is normal to find some slowdown with qiskit.aer since PennyLane is optimized to work with PennyLane devices. In this case my suggestion would be to reduce the size of your problem. For instance if you reduce the number of qubits to 2 you get an answer in about 4min and for 3 qubits it takes about 12min. If you wait long enough you probably get an answer for more qubits. If your program runs out of memory then you can try our circuit-cutting functionality. You can read more about it in the docs or the release blog.

Please let me know if this helps!