How to export parametrized circuit from PennyLane to Qiskit?

I’m working on a QML workflow in which I first use PennyLane to optimize ansatz parameters, next I want to run the inference using pure Qiskit code.
To make this pipeline efficient I’d like to export from PennyLane circuit with ansatz in the parameterized format of Qiskit.
The code below defines a toy 2-qubit circuit with 2 parameters. The function from pennylane_qiskit import load is not returning Qiskit circuit, only <class ‘function’>

import pennylane as qml
from pennylane import numpy as np
from pennylane_qiskit import load
dev = qml.device('default.qubit', wires=2, shots=10)
@qml.qnode(dev)
def circuit(params):
    qml.RX(params[0], wires=0)
    qml.RZ(params[1], wires=0)
    qml.CNOT(wires=[0, 1])
    return [qml.sample(qml.PauliZ(i)) for i in range(2)]
params = np.array([0.7, 0.2])
print(qml.draw(circuit, decimals=2)(params),)
qk_qc=load(circuit)
print(type(qk_qc))

Is it possible to obtain from PennyLane the output below exactly, including user provided names of parameters, so I can bind them to values in Qiskit later? Plan B is I re-type the same ansatz in Qiskit and only export from PennyLane the trained weights.
This is the output I’d like to see from print(load(circuit)):

        ┌────────┐┌────────┐      ░ ┌─┐   
   q_0: ┤ Rx(φ0) ├┤ Rz(φ1) ├──■───░─┤M├───
        └────────┘└────────┘┌─┴─┐ ░ └╥┘┌─┐
   q_1: ────────────────────┤ X ├─░──╫─┤M├
                            └───┘ ░  ║ └╥┘
meas: 2/═════════════════════════════╩══╩═
                                     0  1 

Hi @Jan_Balewski! We do have better support for importing from Qiskit into PennyLane, you can check out out quickstart guide for more details.

To go in the other direction, i.e., PennyLane to Qiskit, you would need to create a QuantumTape and then call the to_openqasm method to get an OpenQASM2 output that can be brought back into Qiskit.

1 Like

While OpenQASM 2 offers many valuable features, it appears to lack the direct constructs for defining parameterized circuits in a manner that’s fully compatible with Qiskit’s approach. This limitation has left me somewhat puzzled as I was initially hopeful for a concise conversion solution, ideally around 5 lines of code. However, understanding that such a conversion might expand into a more complex, I’m considering alternative approaches.
One such approach could involve manually translating PennyLane code snippets into Qiskit. I Appreciate the insights and support provided thus far and understand that if a simple resolution isn’t available, it may be best for me to explore other avenues. Thank you for your time and assistance; it’s greatly appreciated as I navigate through these options.

Hey @Jan_Balewski!

Just to add to what Tom said, pennylane_qiskit.load (load — PennyLane-Qiskit 0.36.0-dev documentation) indeed returns a function that corresponds to the resulting PennyLane template; it’s doing Qiskit → PennyLane, not PennyLane → Qiskit. If I try to run your code and call the qk_qc function, this is what happens:

qk_qc()
ValueError: The circuit <QNode: device='<default.qubit device (wires=2, shots=10) at 0x302f47dd0>', interface='auto', diff_method='best'> is not a valid Qiskit QuantumCircuit.

This happens because you gave it a QNode, not a qiskit circuit :slight_smile:.

Ideally, what you need is for Qiskit to make a qiskit-pennylane plugin, which doesn’t exist :sweat_smile:! But, as Tom said, most quantum programming languages will talk to OpenQASM no problem! You have to do PennyLane → OpenQASM → Qiskit.

Let me know if this helps!