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.

from_pyquil

Loads pyQuil Program objects by using the converter in the PennyLane-Rigetti plugin.

from_qasm

Loads quantum circuits from a QASM string using the converter in the PennyLane-Qiskit plugin.

from_qasm_file

Loads quantum circuits from a QASM file using the converter in the PennyLane-Qiskit plugin.

from_qiskit

Converts a Qiskit QuantumCircuit into a PennyLane quantum function.

from_quil

Loads quantum circuits from a Quil string using the converter in the PennyLane-Rigetti plugin.

from_quil_file

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.

from_qiskit_op

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)