Importing workflows¶
PennyLane supports importing quantum circuits and operations that were constructed using another framework. This includes circuits defined using Qiskit, OpenQASM, and Quil.
Note
To import a quantum circuit defined using a particular framework, you will need to install the corresponding PennyLane plugin for that framework. More information about PennyLane plugins is available on the plugins page.
Importing quantum circuits¶
Importing quantum circuits can help you take advantage of PennyLane’s various optimization, visualization, and interoperability features for existing circuits. For example, you can take a QuantumCircuit from Qiskit, import it into PennyLane, and then apply a circuit-cutting transform to reduce the number of qubits required to implement the circuit. You could also compile the circuit using Catalyst or differentiate and optimize the circuit using quantum-specific optimizers.
Loads pyQuil Program objects by using the converter in the PennyLane-Rigetti plugin. Loads quantum circuits from a QASM string using the converter in the PennyLane-Qiskit plugin. Converts a Qiskit QuantumCircuit into a PennyLane quantum function. Loads quantum circuits from a Quil string using the converter in the PennyLane-Rigetti plugin. Loads quantum circuits from a Quil file using the converter in the PennyLane-Rigetti plugin.
Qiskit¶
Suppose we define a Qiskit QuantumCircuit
as follows:
from qiskit import QuantumCircuit
qk_circuit = QuantumCircuit(2, 1)
qk_circuit.h(0)
qk_circuit.cx(0, 1)
We can convert the QuantumCircuit
into a PennyLane quantum function
using:
import pennylane as qml
pl_qfunc_from_qk = qml.from_qiskit(qk_circuit)
Note
The PennyLane-Qiskit plugin must be
installed to use the from_qiskit()
function.
This quantum function can then be called from inside a QNode to generate a PennyLane circuit:
@qml.qnode(qml.device("default.qubit"))
def pl_circuit_from_qk():
pl_qfunc_from_qk(wires=[0, 1])
return qml.expval(qml.Y(0)), qml.var(qml.Z(1))
Note
Alternatively, the QNode can be instantiated directly from the Qiskit circuit:
measurements = [qml.expval(qml.Y(0)), qml.var(qml.Z(1))]
pl_qfunc_from_qk = qml.from_qiskit(qk_circuit, measurements=measurements)
pl_circuit_from_qk = qml.QNode(pl_qfunc_from_qk, qml.device("default.qubit"))
Here, the measurements
argument overrides any terminal measurements in the Qiskit circuit.
See the from_qiskit()
documentation for more details.
The resulting PennyLane circuit can be executed directly:
>>> pl_circuit_from_qk()
[tensor(0., requires_grad=True), tensor(1., requires_grad=True)]
It can also be visualized using PennyLane’s draw()
utility:
>>> print(qml.draw(pl_circuit_from_qk)())
0: ──H─╭●─┤ <Y>
1: ────╰X─┤ Var[Z]
OpenQASM¶
An equivalent quantum circuit can be expressed in OpenQASM 2.0 as follows:
oq_circuit = (
"""
OPENQASM 2.0;
include "qelib1.inc";
qreg q[2];
creg c[2];
h q[0];
cx q[0], q[1];
"""
)
We can import this circuit into PennyLane using the PennyLane-Qiskit plugin once more:
import pennylane as qml
pl_qfunc_from_oq = qml.from_qasm(oq_circuit)
@qml.qnode(qml.device("default.qubit"))
def pl_circuit_from_oq():
pl_qfunc_from_oq(wires=[0, 1])
return qml.expval(qml.Y(0)), qml.var(qml.Z(1))
The result is as follows:
>>> print(qml.draw(pl_circuit_from_oq)())
0: ──H─╭●─┤ <Y>
1: ────╰X─┤ Var[Z]
Quil¶
PennyLane also offers convenience functions for importing circuits from pyQuil or Quil representations. Both of these require the PennyLane-Rigetti plugin.
We begin with a familiar pyQuil Program:
import pyquil
pq_program = pyquil.Program()
pq_program += pyquil.gates.H(0)
pq_program += pyquil.gates.CNOT(0, 1)
This Program
can be converted into a PennyLane quantum function using the
from_pyquil()
function:
import pennylane as qml
pl_qfunc_from_pq = qml.from_pyquil(pq_program)
@qml.qnode(qml.device("default.qubit"))
def pl_circuit_from_pq():
pl_qfunc_from_pq(wires=[0, 1])
return qml.expval(qml.Y(0)), qml.var(qml.Z(1))
The resulting PennyLane circuit is:
>>> print(qml.draw(pl_circuit_from_pq)())
0: ──H─╭●─┤ <Y>
1: ────╰X─┤ Var[Z]
Note
Quantum circuits expressed in Quil can be imported in a similar way using
from_quil()
.
Importing quantum operators¶
As well as circuits, it can be useful to import operators defined in other frameworks into PennyLane. This can be useful for workflows that involve calculating the expectation value of an observable. By mapping to PennyLane, we can make the workflow differentiable while maintaining access to features like grouping for hardware-efficient execution.
Converts a Qiskit SparsePauliOp into a PennyLane
Operator
.
Presently, only Qiskit SparsePauliOp operators can be
imported into PennyLane. To see this in action, we first define a SparsePauliOp
:
from qiskit.quantum_info import SparsePauliOp
qk_op = SparsePauliOp(["II", "XY"])
Then, we apply the from_qiskit_op()
function to convert the SparsePauliOp
into
a PennyLane Operator
:
import pennylane as qml
pl_op = qml.from_qiskit_op(qk_op)
We can inspect both operators to make sure they match:
>>> qk_op
SparsePauliOp(['II', 'XY'],
coeffs=[1.+0.j, 1.+0.j])
>>> pl_op
I(0) + X(1) @ Y(0)