qml.ftqc.ppr_to_mbqc¶
- ppr_to_mbqc()¶
Specify that the MLIR compiler pass for lowering Pauli Product Rotations (PPR) and Pauli Product Measurements (PPM) to a measurement-based quantum computing (MBQC) style circuit will be applied.
This pass replaces PBC operations (
pbc.pprandpbc.ppm) with a gate-based sequence in the Quantum dialect using universal gates and measurements that are supported as MBQC gate set. For details, see the Figure 2 of Measurement-based Quantum Computation on cluster states.Conceptually, each Pauli product is handled by:
Mapping its Pauli string to the Z basis via per-qubit conjugations (e.g.,
HforX; specializedRotXZXsequences forY).Accumulating parity onto the first qubit with a right-to-left CNOT ladder.
Emitting the kernel operation: - PPR: apply an
RZwith an angle derived from the rotation kind. - PPM: perform a measurement and return ani1result.Uncomputing by reversing the CNOT ladder and the conjugations.
Conjugating the qubits back to the original basis.
Note
This pass expects PPR/PPM operations to be present. In practice, use it after
to_ppr.Example
Convert a simple Clifford+T circuit to PPRs, then lower them to an MBQC-style circuit. Note that this pass should be applied before
ppr_to_ppmsince it requires the actual PPR/PPM operations.import pennylane as qml from pennylane.ftqc.decomposition import ppr_to_mbqc from pennylane.transforms.decompositions import to_ppr p = [("my_pipe", ["quantum-compilation-stage"])] @qml.qjit(pipelines=p, target="mlir", keep_intermediate=True) @ppr_to_mbqc @to_ppr @qml.qnode(qml.device("null.qubit", wires=2)) def circuit(): qml.H(0) qml.CNOT([0, 1]) return print(circuit.mlir_opt)
Example MLIR excerpt (structure only):
... %cst = arith.constant -1.5707963267948966 : f64 %cst_0 = arith.constant 1.5707963267948966 : f64 %0 = quantum.alloc( 2) : !quantum.reg %1 = quantum.extract %0[ 0] : !quantum.reg -> !quantum.bit %2 = quantum.extract %0[ 1] : !quantum.reg -> !quantum.bit %out_qubits = quantum.custom "RZ"(%cst_0) %1 : !quantum.bit %out_qubits_1 = quantum.custom "H"() %out_qubits : !quantum.bit %out_qubits_2 = quantum.custom "RZ"(%cst_0) %out_qubits_1 : !quantum.bit %out_qubits_3 = quantum.custom "H"() %out_qubits_2 : !quantum.bit %out_qubits_4 = quantum.custom "RZ"(%cst_0) %out_qubits_3 : !quantum.bit %out_qubits_5 = quantum.custom "H"() %2 : !quantum.bit %out_qubits_6:2 = quantum.custom "CNOT"() %out_qubits_5, %out_qubits_4 : !quantum.bit, !quantum.bit %out_qubits_7 = quantum.custom "RZ"(%cst_0) %out_qubits_6#1 : !quantum.bit %out_qubits_8:2 = quantum.custom "CNOT"() %out_qubits_6#0, %out_qubits_7 : !quantum.bit, !quantum.bit %out_qubits_9 = quantum.custom "H"() %out_qubits_8#0 : !quantum.bit %out_qubits_10 = quantum.custom "RZ"(%cst) %out_qubits_8#1 : !quantum.bit %out_qubits_11 = quantum.custom "H"() %out_qubits_9 : !quantum.bit %out_qubits_12 = quantum.custom "RZ"(%cst) %out_qubits_11 : !quantum.bit %out_qubits_13 = quantum.custom "H"() %out_qubits_12 : !quantum.bit %mres, %out_qubit = quantum.measure %out_qubits_13 : i1, !quantum.bit ...