0.35.1version question

Previously, the code was running with PennyLane version 0.23.0 and Python version 3.8.10. However, when I switched to the latest environment with PennyLane version 0.35.1 and Python version 3.9.13, issues occurred.

my main code

import torch
import torch.nn as nn
import torch.nn.functional as F
import pennylane as qml
from math import ceil
from math import pi
torch.manual_seed(0)
n_qubits = 4
n_layers = 1
n_class = 3
n_features = 196
image_x_y_dim = 14
kernel_size = n_qubits
stride = 2
dev = qml.device("default.qubit", wires=n_qubits)

def circuit(inputs, weights):
    var_per_qubit = int(len(inputs) / n_qubits) + 1
    encoding_gates = ['RZ', 'RY'] * ceil(var_per_qubit / 2)
    for qub in range(n_qubits):
        qml.Hadamard(wires=qub)
        for i in range(var_per_qubit):
            if (qub * var_per_qubit + i) < len(inputs):
                exec('qml.{}({}, wires = {})'.format(encoding_gates[i], inputs[qub * var_per_qubit + i], qub))
            else:  # load nothing
                pass

    for l in range(n_layers):
        for i in range(n_qubits):
            qml.CRZ(weights[l, i], wires=[i, (i + 1) % n_qubits])
            # qml.CNOT(wires = [i, (i + 1) % n_qubits])
        for j in range(n_qubits, 2 * n_qubits):
            qml.RY(weights[l, j], wires=j % n_qubits)

    _expectations = [qml.expval(qml.PauliZ(i)) for i in range(n_qubits)]
    return _expectations
    # return qml.expval(qml.PauliZ(0))


class Quanv2d(nn.Module):
    def __init__(self, kernel_size=None, stride=None):
        super(Quanv2d, self).__init__()
        weight_shapes = {"weights": (n_layers, 2 * n_qubits)}
        qnode = qml.QNode(circuit, dev, interface='torch', diff_method='best')
        self.ql1 = qml.qnn.TorchLayer(qnode, weight_shapes)
        self.kernel_size = kernel_size
        self.stride = stride

    def forward(self, X):
        assert len(X.shape) == 4  # (bs, c, w, h)
        bs = X.shape[0]
        XL = []
        for i in range(0, X.shape[2] - 2, stride):
            for j in range(0, X.shape[3] - 2, stride):
                XL.append(self.ql1(torch.flatten(X[:, :, i:i + kernel_size, j:j + kernel_size], start_dim=1)))
        X = torch.cat(XL, dim=1).view(bs, 4, 6, 6)
        return X


class Inception(nn.Module):
    def __init__(self, in_channels):
        super(Inception, self).__init__()

        self.branchClassic_1 = nn.Conv2d(in_channels, 4, kernel_size=1, stride=1)
        self.branchClassic_2 = nn.Conv2d(4, 8, kernel_size=4, stride=2)

        self.branchQuantum = Quanv2d(kernel_size=4, stride=2)

    def forward(self, x):
        classic = self.branchClassic_1(x)
        classic = self.branchClassic_2(classic)

        quantum = self.branchQuantum(x)

        outputs = [classic, quantum]
        return torch.cat(outputs, dim=1)


class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.incep = Inception(in_channels=1)
        self.fc1 = nn.Linear(12 * 6 * 6, n_class*2)
        self.fc2 = nn.Linear(n_class*2, n_class)
        self.lr = nn.LeakyReLU(0.1)

    def forward(self, x):
        bs = x.shape[0]
        x = x.view(bs, 1, 14, 14)
        x = self.incep(x)
        x = self.lr(x)

        x = x.view(bs, -1)
        x = self.lr(self.fc1(x))
        x = self.fc2(x)
        return x

full error message below:

Traceback (most recent call last):
  File "/mnt/second_drive/user_data/ztx/quantum_MachineLearning/study/QC-CNN-main/run.py", line 47, in <module>
    train_network(net=net1, train_set=train_set, val_set=val_set, device=device,
  File "/mnt/second_drive/user_data/ztx/quantum_MachineLearning/study/QC-CNN-main/app/train.py", line 43, in train_network
    output = net(data)
  File "/usr/local/anaconda3/lib/python3.9/site-packages/torch/nn/modules/module.py", line 1501, in _call_impl
    return forward_call(*args, **kwargs)
  File "/mnt/second_drive/user_data/ztx/quantum_MachineLearning/study/QC-CNN-main/models/inception.py", line 94, in forward
    x = self.incep(x)
  File "/usr/local/anaconda3/lib/python3.9/site-packages/torch/nn/modules/module.py", line 1501, in _call_impl
    return forward_call(*args, **kwargs)
  File "/mnt/second_drive/user_data/ztx/quantum_MachineLearning/study/QC-CNN-main/models/inception.py", line 77, in forward
    quantum = self.branchQuantum(x)
  File "/usr/local/anaconda3/lib/python3.9/site-packages/torch/nn/modules/module.py", line 1501, in _call_impl
    return forward_call(*args, **kwargs)
  File "/mnt/second_drive/user_data/ztx/quantum_MachineLearning/study/QC-CNN-main/models/inception.py", line 59, in forward
    XL.append(self.ql1(torch.flatten(X[:, :, i:i + kernel_size, j:j + kernel_size], start_dim=1)))
  File "/usr/local/anaconda3/lib/python3.9/site-packages/torch/nn/modules/module.py", line 1501, in _call_impl
    return forward_call(*args, **kwargs)
  File "/mnt/second_drive/user_data/ztx/.local/lib/python3.9/site-packages/pennylane/qnn/torch.py", line 402, in forward
    results = self._evaluate_qnode(inputs)
  File "/mnt/second_drive/user_data/ztx/.local/lib/python3.9/site-packages/pennylane/qnn/torch.py", line 423, in _evaluate_qnode
    res = self.qnode(**kwargs)
  File "/mnt/second_drive/user_data/ztx/.local/lib/python3.9/site-packages/pennylane/workflow/qnode.py", line 1002, in __call__
    self.construct(args, kwargs)
  File "/mnt/second_drive/user_data/ztx/.local/lib/python3.9/site-packages/pennylane/workflow/qnode.py", line 888, in construct
    self._qfunc_output = self.func(*args, **kwargs)
  File "/mnt/second_drive/user_data/ztx/quantum_MachineLearning/study/QC-CNN-main/models/inception.py", line 28, in circuit
    exec('qml.{}({}, wires = {})'.format(encoding_gates[i], inputs[qub * var_per_qubit + i], qub))
  File "<string>", line 1, in <module>
NameError: name 'tensor' is not defined

qml.about().

Name: PennyLane
Version: 0.35.1
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: GitHub - PennyLaneAI/pennylane: PennyLane is a cross-platform Python library for differentiable programming of quantum computers. Train a quantum computer the same way as a neural network.
Author:
Author-email:
License: Apache License 2.0
Location: /mnt/second_drive/user_data/ztx/.local/lib/python3.9/site-packages
Requires: appdirs, autograd, autoray, cachetools, networkx, numpy, pennylane-lightning, requests, rustworkx, scipy, semantic-version, toml, typing-extensions
Required-by: PennyLane_Lightning, PennyLane_Lightning_GPU

Platform info: Linux-5.15.0-101-generic-x86_64-with-glibc2.31
Python version: 3.9.13
Numpy version: 1.26.4
Scipy version: 1.12.0
Installed devices:

  • lightning.qubit (PennyLane-Lightning-0.35.1)
  • default.clifford (PennyLane-0.35.1)
  • default.gaussian (PennyLane-0.35.1)
  • default.mixed (PennyLane-0.35.1)
  • default.qubit (PennyLane-0.35.1)
  • default.qubit.autograd (PennyLane-0.35.1)
  • default.qubit.jax (PennyLane-0.35.1)
  • default.qubit.legacy (PennyLane-0.35.1)
  • default.qubit.tf (PennyLane-0.35.1)
  • default.qubit.torch (PennyLane-0.35.1)
  • default.qutrit (PennyLane-0.35.1)
  • null.qubit (PennyLane-0.35.1)
  • lightning.gpu (PennyLane-Lightning-GPU-0.35.1)

Hey @tx_z, welcome to the forum! :rocket:

I think I’m missing part of your code to try and replicate the issue. What you attached just contains class and quantum function definitions that aren’t called or instantiated after the fact (so the code executes just fine for me). What are you trying to run after you define your quantum function and your classes?

Sorry@ isaacdevlugt, I didn’t check this message promptly as I’ve been dealing with other issues lately. I’ve uploaded the entire project to GitHub. You can view the complete code at https://github.com/optimisticztx/QC-CNN-main/tree/ztx/QC-CNN-main and run the project using run.py.

Hey @tx_z, the code base on your repo is quite large. It’ll be quite time consuming for me to parse through it and figure out where the problem is :sweat_smile:.

Based on the error message, something is going on in your circuit function in inception.py:

def circuit(inputs, weights):
    var_per_qubit = int(len(inputs) / n_qubits) + 1
    encoding_gates = ['RZ', 'RY'] * ceil(var_per_qubit / 2)
    for qub in range(n_qubits):
        qml.Hadamard(wires=qub)
        for i in range(var_per_qubit):
            if (qub * var_per_qubit + i) < len(inputs):
                exec('qml.{}({}, wires = {})'.format(encoding_gates[i], inputs[qub * var_per_qubit + i], qub))
            else:  # load nothing
                pass

Specifically, this line:

                exec('qml.{}({}, wires = {})'.format(encoding_gates[i], inputs[qub * var_per_qubit + i], qub))

I would try printing some of the arguments to exec to see what it’s stopping on. Then you can try to match that to something in our deprecations and breaking changes (release notes: Release notes — PennyLane 0.35.1 documentation, deprecations: Deprecations — PennyLane 0.35.1 documentation)

Let me know if that helps!

@ isaacdevlugtThank you for your response, that’s exactly where the problem lies. I have modified my code.

def circuit(inputs, weights):
    var_per_qubit = int(len(inputs) / n_qubits) + 1
    encoding_gates = ['RZ', 'RY'] * ceil(var_per_qubit / 2)
    for qub in range(n_qubits):
        qml.Hadamard(wires=qub)
        for i in range(var_per_qubit):
            if (qub * var_per_qubit + i) < len(inputs):
                if encoding_gates[i] == 'RZ':
                    qml.RZ(inputs[qub * var_per_qubit + i], wires=qub)
                elif encoding_gates[i] == 'RY':
                    qml.RY(inputs[qub * var_per_qubit + i], wires=qub)
            else:  # load nothing
                pass
...

Subsequently, the following issue occurred during training.

RuntimeError: shape '[32, -1]' is invalid for input of size 16

Then I modified the forward function in my Quanv2d class to iterate over each batch, but I wonder why it could run directly in the older version (Python 3.8.10, PennyLane 0.24.0)?

# Before the modification.
    def forward(self, X):
        assert len(X.shape) == 4  # (bs, c, w, h)
        bs = X.shape[0]
        XL = []
        for i in range(0, X.shape[2] - 2, stride):
            for j in range(0, X.shape[3] - 2, stride):
                XL.append(self.ql1(torch.flatten(X[:, :, i:i + kernel_size, j:j + kernel_size], start_dim=1)))
        X = torch.cat(XL, dim=1).view(bs, 4, 6, 6)
        return X
# After the modification.
    def forward(self, X):
        assert len(X.shape) == 4  # (bs, c, w, h)
        bs = X.shape[0]
        XB = []
        for b in range(0, bs):
            XL = []
            for i in range(0, X.shape[2] - 2, stride):
                for j in range(0, X.shape[3] - 2, stride):
                    tt = torch.flatten(X[b, :, i:i + kernel_size, j:j + kernel_size], start_dim=0)
                    xx = self.ql1(tt)
                    XL.append(xx)
            XB.append(torch.cat(XL, dim=0).view(4, 6, 6))
        X = torch.stack(XB, dim=0)
        return X

Sincerely thank you!

Hi @tx_z ,

It’s great to see that you solved the problem!

My guess is that the reason why your previous code didn’t work with the latest version of PennyLane is because of our change in QNode returns.

As of version 0.30 of PennyLane QNode returns became more intuitive in the sense that they returned exactly what you would expect them to return. Before, the format in which things were returned wasn’t always obvious. It’s possible that the issue was somewhere else entirely but this is my intuition on the problem.

You can learn more about the change in QNode returns here in the docs.

Let us know if you have any further questions!