# Unexpected recursion error qml minimization

I’m using pennylane qml to minimize a cost function involving certain circuits. I’m unexpectedly running into a ‘max recursion depth error’. Here is my code:

``````from scipy import linalg
import pennylane as qml
import numpy as np

qbts=3
layers=3
params=layers*qbts + 2
all_wires = [i for i in range(qbts)]
ansatz_wires = all_wires[1:]
dev = qml.device("default.qubit", analytic=True, wires=qbts+1)
@qml.template
def ansatz(params):
param_idx = 0
for i in ansatz_wires:
qml.RY(params[param_idx], wires=i)
param_idx=param_idx+1

for _ in range(layers-1):
for i in range(qbts):
if i+1 == qbts:
qml.CNOT(wires=[i,0])
else:
qml.CNOT(wires=[i,i+1])

for i in range(qbts):
qml.RY(params[param_idx], wires=i)
param_idx=param_idx+1
@qml.template

@qml.qnode(dev)
def circuit(l2,l1,U):

ansatz(l1)
for u in U[::-1]:
qml.inv(ansatz(l2))

return qml.expval(qml.PauliZ(0))

def cost(l2,l1,U):
psi = circuit(l2[2:],l1[2:],U)
psi = [np.round(_,decimals=5) for _ in psi]
return np.linalg.norm(np.array(psi)-np.linalg.norm(fx))

g0 = .02
def CostFunctionReal(l_new, l_old, g0=g0):
l2 = l_new[2:]
l1 = l_old[2:]
R1=circuit(l2,l1,[ ])
R2=circuit(l2,l1,['a']) #******* Issue caused by this line
return R1 + R2
def costMin(l_old):
return lambda l_new:CostFunctionReal(l_new,l_old)

x0 = 4*np.pi*np.random.rand(params)
x = opt.step(costMin(x0), x0)
``````

As you can see, by the commented code, the issue is caused when I use the Cadder() circuit in the cost function CostFunctionReal(…) when setting the R2 term. Your feedback on fixing this error would be much appreciated. Thanks.

Hey @matp!

I managed to get it to work by setting `U` as a keyword argument:

``````from scipy import linalg
import pennylane as qml
from pennylane import numpy as np

qbts=3
layers=3
params=layers*qbts + 2

all_wires = [i for i in range(qbts)]
ansatz_wires = all_wires[1:]

adder_matrix = np.diag(np.ones(2**qbts - 1), -1)

dev = qml.device("default.qubit", analytic=True, wires=qbts+1)

@qml.template
def ansatz(params):
param_idx = 0
for i in ansatz_wires:
qml.RY(params[param_idx], wires=i)
param_idx=param_idx+1

for _ in range(layers-1):
for i in range(qbts):
if i+1 == qbts:
qml.CNOT(wires=[i,0])
else:
qml.CNOT(wires=[i,i+1])

for i in range(qbts):
qml.RY(params[param_idx], wires=i)
param_idx=param_idx+1

@qml.template

@qml.qnode(dev)
def circuit(l2,l1,U=None):

ansatz(l1)
for u in U[::-1]:
if u == 'a':
qml.inv(ansatz(l2))

return qml.expval(qml.PauliZ(0))

def cost(l2,l1,U):
psi = circuit(l2[2:],l1[2:],U)
psi = [np.round(_,decimals=5) for _ in psi]
return np.linalg.norm(np.array(psi)-np.linalg.norm(fx))

l1 = np.random.random(params)
l2 = np.random.random(params)

c1 = circuit(l2, l1, U=[])
c2 = circuit(l2, l1, U=["a"])

print(c1, c2)
``````

You can see in the code above that we use `def circuit(l2,l1,U=None)`, which allows the QNode to not worry about differentiating with respect to `U`. I think having a list of strings was confusing `autograd`, which is the default interface for supporting differentiation of the QNode.

Some other changes in the above:

• Had to user `adder_matrix` rather than `c_adder` as the unitary in `Cadder` since `c_adder` was of too big dimension
• You should do `from pennylane import numpy as np` so that numpy functionality can keep track of the gradient (see here)

Hope this helps!

Thank you very much, I was able to solve the issue thanks to your feedback!

1 Like