create_expand_fn(depth, stop_at=None, device=None, docstring=None)[source]

Create a function for expanding a tape to a given depth, and with a specific stopping criterion. This is a wrapper around expand().

  • depth (int) – Depth for the expansion

  • stop_at (callable) – Stopping criterion. This must be a function with signature stop_at(obj), where obj is a queueable PennyLane object such as Operation or MeasurementProcess. It must return a boolean, indicating if the expansion should stop at this object.

  • device (Device) – Ensure that the expanded tape only uses native gates of the given device.

  • docstring (str) – docstring for the generated expansion function


Tape expansion function. The returned function accepts a QuantumTape, and returns an expanded QuantumTape.

Return type



Let us construct an expansion function that expands a tape in order to decompose trainable multi-parameter gates. We allow for up to five expansion steps, which can be controlled with the argument depth. The stopping criterion is easy to write as

>>> stop_at = ~(qml.operation.has_multipar & qml.operation.is_trainable)

Then the expansion function can be obtained via

>>> expand_fn = qml.transforms.create_expand_fn(depth=5, stop_at=stop_at)

We can test the newly generated function on an example tape:

with qml.tape.QuantumTape() as tape:
    qml.RX(0.2, wires=0)
    qml.RX(qml.numpy.array(-2.4, requires_grad=True), wires=1)
    qml.Rot(1.7, 0.92, -1.1, wires=0)
    qml.Rot(*qml.numpy.array([-3.1, 0.73, 1.36], requires_grad=True), wires=1)
>>> new_tape = expand_fn(tape)
>>> print(qml.drawer.tape_text(tape, decimals=1))
0: ──RX(0.2)───Rot(1.7,0.9,-1.1)─┤
1: ──RX(-2.4)──Rot(-3.1,0.7,1.4)─┤
>>> print(qml.drawer.tape_text(new_tape, decimals=1))
0: ──RX(0.2)───Rot(1.7,0.9,-1.1)───────────────────┤
1: ──RX(-2.4)──RZ(-3.1)───────────RY(0.7)──RZ(1.4)─┤