catalyst.passes.ppr_to_ppm

ppr_to_ppm(qnode=None, *, decompose_method='pauli-corrected', avoid_y_measure=False)[source]

A quantum compilation pass that decomposes Pauli product rotations (PPRs), \(P(\theta) = \exp(-iP\theta)\), into Pauli product measurements (PPMs).

Note

For improved integration with the PennyLane frontend, including inspectability with pennylane.specs(), please use pennylane.transforms.ppr_to_ppm().

This pass is used to decompose both non-Clifford and Clifford PPRs into PPMs. The non-Clifford PPRs (\(\theta = \tfrac{\pi}{8}\)) are decomposed first, then Clifford PPRs (\(\theta = \tfrac{\pi}{4}\)) are decomposed.

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

  • decompose_method (str, optional) – The method to use for decomposing non-Clifford PPRs. Options are "pauli-corrected", "auto-corrected", and "clifford-corrected". Defaults to "pauli-corrected". "pauli-corrected" uses a reactive measurement for correction. "auto-corrected" uses an additional measurement for correction. "clifford-corrected" uses a Clifford rotation for correction.

  • avoid_y_measure (bool) – Rather than performing a Pauli-Y measurement for Clifford rotations (sometimes more costly), a \(Y\) state (\(Y\vert 0 \rangle\)) is used instead (requires \(Y\) state preparation). This is currently only supported when using the "clifford-corrected" and "pauli-corrected" decomposition method. Defaults to False.

Returns:

QNode

Example

This example shows the sequence of passes that will be applied. The last pass will convert the non-Clifford PPR into Pauli Product Measurements.

import pennylane as qml
import catalyst

p = [("my_pipe", ["quantum-compilation-stage"])]

@qml.qjit(pipelines=p, target="mlir")
@catalyst.passes.ppr_to_ppm(decompose_method="auto-corrected")
@catalyst.passes.merge_ppr_ppm
@catalyst.passes.commute_ppr
@catalyst.passes.to_ppr
@qml.qnode(qml.device("null.qubit", wires=2))
def circuit():
    qml.H(0)
    qml.T(0)
    qml.CNOT([0, 1])
    return catalyst.measure(0), catalyst.measure(1)

print(circuit.mlir_opt)

Because Catalyst does not currently support execution of Pauli-based computation operations, we must halt the pipeline after quantum-compilation-stage. This ensures that only the quantum passes will be applied to the initial MLIR, without attempting to further compile for execution.

Example MLIR Representation:

. . .
%3 = qec.fabricate  magic : !quantum.bit
%mres, %out_qubits:2 = qec.ppm ["X", "Z"] %1, %3 : i1, !quantum.bit, !quantum.bit
%mres_0, %out_qubits_1:2 = qec.ppm ["Z", "Y"](-1) %out_qubits#1, %2 : i1, !quantum.bit, !quantum.bit
%mres_2, %out_qubits_3 = qec.ppm ["X"] %out_qubits_1#0 : i1, !quantum.bit
%mres_4, %out_qubits_5 = qec.select.ppm(%mres, ["X"], ["Z"]) %out_qubits_1#1 : i1, !quantum.bit
%4 = arith.xori %mres_0, %mres_2 : i1
%5 = qec.ppr ["X"](2) %out_qubits#0 cond(%4) : !quantum.bit
. . .