Converting QCNN from Qiskit

I am trying to convert the QCNN model as defined here into Pennylane - https://qiskit-community.github.io/qiskit-machine-learning/tutorials/11_quantum_convolutional_neural_networks.html.

I have downloaded their notebook and only written the following code to perform the conversion and testing.

dev = qml.device('default.qubit', wires = 8)

@qml.qnode(dev,interface='torch')
def qcnn(c1,c2,c3,p1,p2,p3,x):
    qml.from_qiskit(circuit)(c1,c2,c3,p1,p2,p3,x)
    return qml.expval(qml.PauliZ(7))

# random parameters
c1 = np.random.random(24)*2-1
c2 = np.random.random(12)*2-1
c3 = np.random.random(6)*2-1
p1 = np.random.random(12)*2-1
p2 = np.random.random(6)*2-1
p3 = np.random.random(3)*2-1

# runs forward pass using converted
qcnn(c1,c2,c3,p1,p2,p3,train_images[0])
# runs forward pass using original
qnn.forward(train_images[0], np.concatenate([c1,c2,c3,p1,p2,p3]))

The forward pass runs but does not give the same output. The converted model only seems to output ‘1’. The following warnings are given when performing the forward pass.

UserWarning: pennylane_qiskit.converter: The Gate instruction is not supported by PennyLane, and has not been added to the template.
 
UserWarning: pennylane_qiskit.converter: The Instruction instruction is not supported by PennyLane, and has not been added to the template.

The output of qml.about() is below:

Name: PennyLane
Version: 0.39.0
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 quantum computing, quantum machine learning, and quantum chemistry. Train a quantum computer the same way as a neural network.
Author:
Author-email:
License: Apache License 2.0
Location: e:\qiskit\Lib\site-packages
Requires: appdirs, autograd, autoray, cachetools, networkx, numpy, packaging, pennylane-lightning, requests, rustworkx, scipy, toml, typing-extensions
Required-by: PennyLane-qiskit, PennyLane_Lightning

Platform info: Windows-11-10.0.22631-SP0
Python version: 3.12.4
Numpy version: 2.0.2
Scipy version: 1.14.1
Installed devices:

  • default.clifford (PennyLane-0.39.0)
  • default.gaussian (PennyLane-0.39.0)
  • default.mixed (PennyLane-0.39.0)
  • default.qubit (PennyLane-0.39.0)
  • default.qutrit (PennyLane-0.39.0)
  • default.qutrit.mixed (PennyLane-0.39.0)
  • default.tensor (PennyLane-0.39.0)
  • null.qubit (PennyLane-0.39.0)
  • reference.qubit (PennyLane-0.39.0)
  • lightning.qubit (PennyLane_Lightning-0.39.0)
  • qiskit.aer (PennyLane-qiskit-0.39.1)
  • qiskit.basicaer (PennyLane-qiskit-0.39.1)
  • qiskit.basicsim (PennyLane-qiskit-0.39.1)
  • qiskit.remote (PennyLane-qiskit-0.39.1)

Hi @DOC1 ,

Welcome to the Forum!

It looks like you need to use circuit.decompose() instead of just circuit.

Also, for some reason the first time I ran your code it wouldn’t properly identify the wires, but the second time running the code it would (no idea why). This can be fixed by removing the wire assignment in default.qubit and letting this device figure out how many qubits it needs. Then the code runs well.

dev = qml.device('default.qubit') # let the wires be assigned automatically for default.qubit

@qml.qnode(dev,interface='torch')
def qcnn(c1,c2,c3,p1,p2,p3,x):
    qml.from_qiskit(circuit.decompose())(c1,c2,c3,p1,p2,p3,x) # use circuit.decompose() here
    return qml.expval(qml.PauliZ(7))

Let me know if this works for you!

Hi @CatalinaAlbornoz, thanks for your help, the code now works as expected. Just for my understanding, is calling decompose() necessary because the notebook creates the circuit by calling to_instruction()?

Hi @DOC1 ,

I’m not a Qiskit expert, but I think that’s exactly why. From my understanding to_instruction() creates an Instruction instead of an actual circuit which is why you need to .decompose() in order to use Qiskit’s draw() or convert it to PennyLane.