qml.transforms.commute_ppr

commute_ppr(tape, *, max_pauli_size=0)[source]

A quantum compilation pass that commutes Clifford Pauli product rotation (PPR) gates, \(\exp(-{iP\tfrac{\pi}{4}})\), past non-Clifford PPRs gates, \(\exp(-{iP\tfrac{\pi}{8}})\), where \(P\) is a Pauli word.

Note

This transform requires decorating the workflow with @qml.qjit. In addition, the circuits generated by this pass are currently not executable on any backend. This pass is only for Pauli-based-computation analysis with the null.qubit device and potential future execution when a suitable backend is available.

Lastly, the pennylane.transforms.to_ppr() transform must be applied before commute_ppr.

For more information on PPRs, check out the Compilation Hub.

Parameters:
  • fn (QNode) – QNode to apply the pass to.

  • max_pauli_size (int) – The maximum size of Pauli strings resulting from commutation. If a commutation results in a PPR that acts on more than max_pauli_size qubits, that commutation will not be performed. Note that the default max_pauli_size=0 indicates no limit.

Returns:

QNode

Note

For better compatibility with other PennyLane functionality, ensure that PennyLane program capture is enabled with pennylane.capture.enable().

Example

The commute_ppr compilation pass can be applied as a decorator on a QNode:

import pennylane as qml
import jax.numpy as jnp

qml.capture.enable()

@qml.qjit(target="mlir")
@qml.transforms.commute_ppr(max_pauli_size=2)
@qml.transforms.to_ppr
@qml.qnode(qml.device("null.qubit", wires=2))
def circuit():

    # equivalent to a Hadamard gate
    qml.PauliRot(jnp.pi / 2, pauli_word="Z", wires=0)
    qml.PauliRot(jnp.pi / 2, pauli_word="X", wires=0)
    qml.PauliRot(jnp.pi / 2, pauli_word="Z", wires=0)

    # equivalent to a CNOT gate
    qml.PauliRot(jnp.pi / 2, pauli_word="ZX", wires=[0, 1])
    qml.PauliRot(-jnp.pi / 2, pauli_word="Z", wires=0)
    qml.PauliRot(-jnp.pi / 2, pauli_word="X", wires=1)

    # equivalent to a T gate
    qml.PauliRot(jnp.pi / 4, pauli_word="Z", wires=0)

    return qml.expval(qml.Z(0))

To inspect programs compiled with commute_ppr via specs(), ensure that target="mlir" is given in the qjit decorator.

>>> print(qml.specs(circuit, level=3)())
Device: null.qubit
Device wires: 2
Shots: Shots(total=None)
Level: 3

Resource specifications:
Total wire allocations: 2
Total gates: 7
Circuit depth: Not computed

Gate types:
    PPR-pi/8: 1
    PPR-pi/4: 6

Measurements:
    expval(PauliZ): 1

In the example above, the Clifford PPRs (PauliRot instances with an angle of rotation of \(\tfrac{\pi}{2}\)) will be commuted past the non-Clifford PPR (PauliRot instances with an angle of rotation of \(\tfrac{\pi}{4}\)). In the output above, PPR-theta denotes the type of PPR present in the circuit, where theta is the PPR angle (\(\theta\)).

Note that if a commutation resulted in a PPR acting on more than max_pauli_size qubits (here, max_pauli_size = 2), that commutation would be skipped.