catalyst.passes.commute_ppr

commute_ppr(qnode=None, *, max_pauli_size=0)[source]

Specify that the MLIR compiler pass for commuting Clifford Pauli Product Rotation (PPR) gates, \(\exp({iP\tfrac{\pi}{4}})\), past non-Clifford PPRs gates, \(\exp({iP\tfrac{\pi}{8}})\) will be applied, where \(P\) is a Pauli word.

For more information regarding to PPM, see here <https://pennylane.ai/compilation/pauli-product-measurement>

Note

The commute_ppr compilation pass requires that to_ppr() be applied first.

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

  • max_pauli_size (int) – The maximum size of the Pauli strings after commuting.

Returns:

~.QNode

Example

The commute_ppr pass must be used in conjunction with to_ppr() to first convert gates into PPRs. In this example, the Clifford+T gates in the circuit will be converted into PPRs first, then the Clifford PPRs will be commuted past the non-Clifford PPR.

import pennylane as qml
from catalyst import qjit, measure

ppm_passes = [("PPM", ["to-ppr", "commute-ppr"])]

@qjit(pipelines=ppm_passes, keep_intermediate=True, target="mlir")
@qml.qnode(qml.device("null.qubit", wires=1))
def circuit():
    qml.H(0)
    qml.T(0)
    return measure(0)

print(circuit.mlir_opt)

Example MLIR Representation:

. . .
%2 = qec.ppr ["X"](8) %1 : !quantum.bit
%3 = qec.ppr ["Z"](4) %2 : !quantum.bit
%4 = qec.ppr ["X"](4) %3 : !quantum.bit
%5 = qec.ppr ["Z"](4) %4 : !quantum.bit
%mres, %out_qubits = qec.ppm ["Z"] %5 : !quantum.bit
. . .

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.

from catalyst.passes import to_ppr, commute_ppr

pips = [("pipe", ["enforce-runtime-invariants-pipeline"])]

@qjit(pipelines=pips, target="mlir")
@to_ppr
@commute_ppr(max_pauli_size=2)
@qml.qnode(qml.device("lightning.qubit", wires=3))
def circuit():
    qml.H(0)
    qml.CNOT([1, 2])
    qml.CNOT([0, 1])
    qml.CNOT([0, 2])
    for i in range(3):
        qml.T(i)
    return measure(0), measure(1), measure(2)

print(circuit.mlir_opt)

Example MLIR Representation:

. . .
%4:2 = qec.ppr ["Z", "X"](4) %2, %3 : !quantum.bit, !quantum.bit
. . .
%6:2 = qec.ppr ["X", "Y"](-8) %5, %4#1 : !quantum.bit, !quantum.bit
. . .