catalyst.passes.to_ppr

to_ppr(qnode)[source]

A quantum compilation pass that converts Clifford+T gates into Pauli Product Rotation (PPR) gates.

Clifford gates are defined as \(\exp(-{iP\tfrac{\pi}{4}})\), where \(P\) is a Pauli word. Non-Clifford gates are defined as \(\exp(-{iP\tfrac{\pi}{8}})\).

For more information on the PPM compilation pass, check out the compilation hub.

Note

The circuits that generated from this pass are currently not executable on any backend. This pass is only for analysis with the null.qubit device and potential future execution when a suitable backend is available.

The full list of supported gates and operations are qml.H, qml.S, qml.T, qml.X, qml.Y, qml.Z, qml.adjoint(qml.S), qml.adjoint(qml.T), qml.CNOT, and catalyst.measure.

Parameters:

fn (QNode) – QNode to apply the pass to

Returns:

QNode

Example

The to_ppr compilation pass can be applied as a dectorator on a QNode:

import pennylane as qml

qml.capture.enable()

@qml.qjit(target="mlir")
@qml.transforms.to_ppr
@qml.qnode(qml.device("null.qubit", wires=2))
def circuit():
    qml.H(0)
    qml.CNOT([0, 1])
    qml.T(0)
    return qml.expval(qml.Z(0))

For clear and inspectable results, use target="mlir" in the qjit decorator, ensure that PennyLane’s program capture is enabled, pennylane.capture.enable(), and call to_ppr from the PennyLane frontend (qml.transforms.to_ppr) instead of with catalyst.passes.to_ppr.

>>> print(qml.specs(circuit, level="all")()['resources'])
{
    'No transforms': ...,
    'Before MLIR Passes (MLIR-0)': ...,
    'to-ppr (MLIR-1)': Resources(
        num_wires=2,
        num_gates=7,
        gate_types=defaultdict(<class 'int'>, {'PPR-pi/4-w1': 5, 'PPR-pi/4-w2': 1, 'PPR-pi/8-w1': 1}),
        gate_sizes=defaultdict(<class 'int'>, {1: 6, 2: 1}),
        depth=None,
        shots=Shots(total_shots=None, shot_vector=())
    )
}

In the above output, PPR-theta-weight denotes the type of PPR present in the circuit, where theta is the PPR angle (\(\theta\)) and weight is the PPR weight.