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 generated from this pass are currently only executable on the lightning.qubit device with program capture enabled.

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
import catalyst

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

@qml.qjit(pipelines=p, target="mlir")
@catalyst.passes.reduce_t_depth
@catalyst.passes.merge_ppr_ppm
@catalyst.passes.commute_ppr
@catalyst.passes.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 catalyst.measure(0), catalyst.measure(1), catalyst.measure(2)
>>> 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 = pbc.ppr [“X”](8) %1 : !quantum.bit %4 = pbc.ppr [“X”](8) %2 : !quantum.bit

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

// layer 3 %9:3 = pbc.ppr [“X”, “X”, “Y”](8) %7#0, %7#1, %8 : !quantum.bit, !quantum.bit, !quantum.bit

%mres, %out_qubits:3 = pbc.ppm [“X”, “X”, “Y”] %9#0, %9#1, %9#2 : i1, !quantum.bit, !quantum.bit, !quantum.bit %mres_0, %out_qubits_1:3 = pbc.ppm [“Y”, “X”, “X”] %out_qubits#0, %out_qubits#1, %out_qubits#2 : i1, !quantum.bit, !quantum.bit, !quantum.bit %mres_2, %out_qubits_3:3 = pbc.ppm [“X”, “Y”, “X”] %out_qubits_1#0, %out_qubits_1#1, %out_qubits_1#2 : i1, !quantum.bit, !quantum.bit, !quantum.bit …