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.,
Tgates) 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.qubitdevice 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:
Example
In the example below, after performing the
catalyst.passes.to_ppr()andcatalyst.passes.merge_ppr_ppm()passes, the circuit contains a depth of four of non-Clifford PPRs. Subsequently applying thereduce_t_depthpass 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)
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.>>> 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:2 = qec.ppr [“Y”, “X”](8) %3, %4 : !quantum.bit, !quantum.bit %6 = quantum.extract %0[ 2] : !quantum.reg -> !quantum.bit %7:3 = qec.ppr [“X”, “Y”, “X”](8) %5#0, %5#1, %6 : !quantum.bit, !quantum.bit, !quantum.bit %8 = qec.ppr [“X”](8) %7#2 : !quantum.bit
// layer 3 %9:3 = qec.ppr [“X”, “X”, “Y”](8) %7#0, %7#1, %8 : !quantum.bit, !quantum.bit, !quantum.bit
%mres, %out_qubits:3 = qec.ppm [“X”, “X”, “Y”] %9#0, %9#1, %9#2 : i1, !quantum.bit, !quantum.bit, !quantum.bit %mres_0, %out_qubits_1:3 = qec.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 = qec.ppm [“X”, “Y”, “X”] %out_qubits_1#0, %out_qubits_1#1, %out_qubits_1#2 : i1, !quantum.bit, !quantum.bit, !quantum.bit …