Lightning.qubit with reuploading model

I have a simple reuploading test model, i.e.

@qml.qnode(dev, diff_method='adjoint') # 'adjoint' or 'parameter-shift'
def qnn_model(params, x):
    for l in range(n_layers):
        for q in range(n_qubits):
            qml.RY(x, wires=q)
        qml.StronglyEntanglingLayers([params[l]], wires=range(n_qubits))
    return qml.expval(qml.PauliZ(0))

Which I trains with default.qubit and parameter-shift differential method. However, there is no way of training it with lightning.qubit and adjoint differentiation. I am getting “TypeError: Rot(): incompatible function arguments“.

TypeError: Rot(): incompatible function arguments. The following argument types are supported:
    1. (self: pennylane_lightning.lightning_qubit_ops.StateVectorC128, arg0: list[int], arg1: bool, arg2: list[float]) -> None
    2. (self: pennylane_lightning.lightning_qubit_ops.StateVectorC128, arg0: list[int], arg1: list[bool], arg2: list[int], arg3: bool, arg4: list[float]) -> None

Invoked with: <pennylane_lightning.lightning_qubit_ops.StateVectorC128 object at 0x7956b30f97b0>, [0], False, [array(<autograd.numpy.numpy_boxes.ArrayBox object at 0x7956b1b9f000>,
      dtype=object), array(<autograd.numpy.numpy_boxes.ArrayBox object at 0x7956b1b9c600>,
      dtype=object), array(<autograd.numpy.numpy_boxes.ArrayBox object at 0x7956b1b9f340>,
      dtype=object)]

I think the problem is that adjoint of the model is incorrect, as it separates and blocks all encoded data from inversed entangling layers. Is there a way of using lightning.qubit (which does not accept ‘parameter-shift’ diff_method) with this type of model?

My system is (the same problem is with version 0.44+):
$qml.about()
Name: pennylane
Version: 0.42.3
Summary: PennyLane is a cross-platform Python library for quantum computing, quantum machine learning, and quantum chemistry. Train a quantum computer the same way as a neural network.
Home-page:
Author:
Author-email:
License-Expression: Apache-2.0
Location: /home/jacob/venv/pl/lib/python3.11/site-packages
Requires: appdirs, autograd, autoray, cachetools, diastatic-malt, networkx, numpy, packaging, pennylane-lightning, requests, rustworkx, scipy, tomlkit, typing_extensions
Required-by: pennylane_lightning

Platform info: Linux-6.8.0-107-generic-x86_64-with-glibc2.35
Python version: 3.11.4
Numpy version: 2.4.4
Scipy version: 1.17.1
Installed devices:

  • lightning.qubit (pennylane_lightning-0.42.0)
  • default.clifford (pennylane-0.42.3)
  • default.gaussian (pennylane-0.42.3)
  • default.mixed (pennylane-0.42.3)
  • default.qubit (pennylane-0.42.3)
  • default.qutrit (pennylane-0.42.3)
  • default.qutrit.mixed (pennylane-0.42.3)
  • default.tensor (pennylane-0.42.3)
  • null.qubit (pennylane-0.42.3)
  • reference.qubit (pennylane-0.42.3).

Hi @Jacob_Cybulski , welcome back to the Forum!

I think the problem is in the parameters and inputs you’re using, not in the device itself. For example, the code below works for me. Let me know if it works for you too!

import pennylane as qml
from pennylane import numpy as pnp

n_layers = 1
n_qubits = 2
dev = qml.device("lightning.qubit", wires=n_qubits)

shape = qml.StronglyEntanglingLayers.shape(n_layers=n_layers, n_wires=n_qubits)
rng = pnp.random.default_rng(12345)
params = rng.random(size=shape)

x = [0.1, 0.2]

@qml.qnode(dev, diff_method='adjoint') # 'adjoint' or 'parameter-shift'
def qnn_model(params, x):
    for l in range(n_layers):
        for q in range(n_qubits):
            qml.RY(x, wires=q)
        qml.StronglyEntanglingLayers([params[l]], wires=range(n_qubits))
    return qml.expval(qml.PauliZ(0))

qnn_model(params, x)

Thanks @CatalinaAlbornoz yes the model works in the forward step but not in the backward step when the adjoint needs to be calculated to get the gradients for the model optimization. If you set the number of layers to 2 and then take the adjoint of the model, you’ll see that it does not work, it is garbled - all reuploading data rotations which interweave the entangling blocks, are all placed in a single group. When we use a default qubit and use a different diff method it all works.

Just to clarify what I said before, if we use the code you’ve included above, let’s change n_layers = 2, then draw the circuit and its adjoint, you will get these two.

The second cannot possibly be an adjoint of the first! This seems to be the cause of problems while training the reuploading model (the model which interweaves encoding blocks with entangling blocks) with lightning.qubit and diff_method=’adjoint’. May be there is a way (similar to torch interface) of identifying which parameters are trainable and which are input, and then performing “adjoint” within step_and_cost? Or, is there another diff_method compatible with lightning.qubit that would deal with this?

Hi @Jacob_Cybulski , thanks for sharing these additional details.

Are you able to share the full code you’re using for this? Basically, aside from changing the number of layers, what code exactly are you adding that’s causing the issues? I just want to rule out any potential issue in the implementation details.