catalyst.passes.reduce_t_depth

reduce_t_depth(qnode)[source]

A quantum compilation pass that reduces the depth and count of non-Clifford Pauli product rotation (PPR, \(P(\theta) = \exp(-iP\theta)\)) operators (e.g., T gates) by commuting PPRs in adjacent layers and merging compatible ones (a layer comprises PPRs that mutually commute). For more details, see Figure 6 of A Game of Surface Codes.

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.

Parameters:

qnode (QNode) – QNode to apply the pass to.

Returns:

Returns decorated QNode.

Return type:

QNode

Example

In the example below, after performing the catalyst.passes.to_ppr() and catalyst.passes.merge_ppr_ppm() passes, the circuit contains a depth of four of non-Clifford PPRs. Subsequently applying the reduce_t_depth pass will move PPRs around via commutation, resulting in a circuit with a smaller PPR depth.

Specifically, in the circuit below, the Pauli-\(X\) PPR (\(\exp(iX\tfrac{\pi}{8})\)) on qubit Q1 will be moved to the first layer, which results in a depth of three non-Clifford PPRs.

import pennylane as qml
from catalyst import qjit, measure
from catalyst.passes import to_ppr, commute_ppr, reduce_t_depth, merge_ppr_ppm

pips = [("pipe", ["quantum-compilation-stage"])]


@qjit(pipelines=pips, target="mlir")
@reduce_t_depth
@merge_ppr_ppm
@commute_ppr
@to_ppr
@qml.qnode(qml.device("null.qubit", wires=3))
def circuit():
    n = 3
    for i in range(n):
        qml.H(wires=i)
        qml.S(wires=i)
        qml.CNOT(wires=[i, (i + 1) % n])
        qml.T(wires=i)
        qml.H(wires=i)
        qml.T(wires=i)

    return

>>> print(circuit.mlir_opt)

. . .
%1 = quantum.extract %0[ 0] : !quantum.reg -> !quantum.bit
%2 = quantum.extract %0[ 1] : !quantum.reg -> !quantum.bit
// layer 1
%3 = qec.ppr ["X"](8) %1 : !quantum.bit
%4 = qec.ppr ["X"](8) %2 : !quantum.bit

// layer 2
%5 = quantum.extract %0[ 2] : !quantum.reg -> !quantum.bit
%6:2 = qec.ppr ["Y", "X"](8) %3, %4 : !quantum.bit, !quantum.bit
%7 = qec.ppr ["X"](8) %5 : !quantum.bit
%8:3 = qec.ppr ["X", "Y", "X"](8) %6#0, %6#1, %7:!quantum.bit, !quantum.bit, !quantum.bit

// layer 3
%9:3 = qec.ppr ["X", "X", "Y"](8) %8#0, %8#1, %8#2:!quantum.bit, !quantum.bit, !quantum.bit
. . .