How the gradient information flows from a circuit to its original circuit?

I’m going to test the calculation of the gradient information when multiple circuits are cascaded. A measurement of the former circuit as an input to the latter. Start with qml.GradientDescentOptimizer,followed by qml and pytorchqml and tensorflow. But it failed at first. So how do I make sure that the gradient information is transmitted when I use cascaded circuits? Except qml.GradientDescentOptimizer, how do I accomplish this with pytorch, tensorflow?

Thank you!

import pennylane as qml
from pennylane import numpy as np
from sklearn import model_selection, datasets

iris=datasets.load_iris() 
X=iris.data[:100] 
Y=iris.target[:100]
X_train, X_test, Y_train, Y_test=model_selection.train_test_split(X, Y, test_size=0.33, random_state=42)

dev0 = qml.device("default.qubit", wires=4)
@qml.qnode(dev0, interface="autograd", diff_method="parameter-shift")
def layer1(X, para, n_qubits=4):
    for j in range(n_qubits):
        qml.RY(X[j], wires=j)

    for i in range(n_qubits):
        qml.RY(para[i], wires=i)
       
    qml.CNOT(wires=[0, 1])
    qml.CNOT(wires=[1, 2])
    qml.CNOT(wires=[2, 3])
    qml.CNOT(wires=[3, 0])

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

dev1 = qml.device("default.qubit", wires=2)
@qml.qnode(dev1, interface="autograd", diff_method="parameter-shift")
def layer2(X, para, n_qubits=2):
    for i in range(n_qubits):
        qml.RY(X[i], wires=i)

    for i in range(n_qubits):
        qml.RY(para[i], wires=i)

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

dev2 = qml.device("default.qubit", wires=2)
@qml.qnode(dev2, interface="autograd", diff_method="parameter-shift")
def layer3(X, para, n_qubits=2):
    for i in range(n_qubits):
        qml.RY(X[i], wires=i)

    for i in range(n_qubits):
        qml.RY(para[i], wires=i)

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

def cost(X,Y,para):

    fea0 = layer1(X, para[0:4])
    fea1 = layer2(fea0, para[4:6])
    pred = layer3(fea1, para[6:8])

    return 0.5*((pred - Y) ** 2)

loss_ls = []
epoch = 10
opt = qml.GradientDescentOptimizer(0.1)
np.random.seed(0)
para = np.random.uniform(0, 2 * np.pi, 10)
opt = qml.GradientDescentOptimizer(0.1)

for m in range(epoch):
    for X_i, Y_i in zip(X_train, Y_train):
        para, loss = opt.step_and_cost(cost, X_i, Y_i, para)
        loss_ls.append(loss)
        print("loss: ", loss)

If you want help with diagnosing an error, please put the full error message below:

     64 for m in range(epoch):
     65     for X_i, Y_i in zip(X_train, Y_train):
---> 66         para, loss = opt.step_and_cost(cost, X_i, Y_i, para)
     67         loss_ls.append(loss)
     68         print("loss: ", loss)

File d:\Software\Anaconda3\anaconda3\envs\pennylane\lib\site-packages\pennylane\optimize\gradient_descent.py:59, in GradientDescentOptimizer.step_and_cost(self, objective_fn, grad_fn, *args, **kwargs)
     39 def step_and_cost(self, objective_fn, *args, grad_fn=None, **kwargs):
     40     """Update trainable arguments with one step of the optimizer and return the corresponding
     41     objective function value prior to the step.
     42 
   (...)
     56         If single arg is provided, list [array] is replaced by array.
     57     """
---> 59     g, forward = self.compute_grad(objective_fn, args, kwargs, grad_fn=grad_fn)
     60     new_args = self.apply_grad(g, args)
     62     if forward is None:

File d:\Software\Anaconda3\anaconda3\envs\pennylane\lib\site-packages\pennylane\optimize\gradient_descent.py:117, in GradientDescentOptimizer.compute_grad(objective_fn, args, kwargs, grad_fn)
     99 r"""Compute gradient of the objective function at the given point and return it along with
    100 the objective function forward pass (if available).
    101 
...
---> 18     qml.RY(para[i], wires=i)
     20 qml.CNOT(wires=[0, 1])
     21 qml.CNOT(wires=[1, 2])

IndexError: list index out of range

And, finally, make sure to include the versions of your packages. Specifically, show us the output of qml.about() .
pennylane 0.33.1
pennylane-lightning 0.33.1
pennylane-qiskit 0.32.0

Hi @SHAN ,

Before starting to debug your code I’d recommend updating your version of PennyLane with python -m pip install pennylane --upgrade. Our latest stable version is v0.37.

I’d recommend choosing a single interface for now and once you get things working you can experiment with others. Out of the three that you mentioned I’d recommend going with Torch first.

Remember that if you go with Torch you will need to use Torch optimizers. You can learn more here in the docs, or in any of these demos, especially this one. I think you could nicely turn each circuit into a TorchLayer and then join them all together in a sequential model.

I hope this helps!