catalyst
catalyst copied to clipboard
Implement a decomposition of non-Clifford PPRs into PPMs
Context: This PR introduces a new pass that decomposes non-Clifford Pauli Product Rotations (PPR) into Pauli Product Measurements (PPMs) consuming magic states. Two decomposition strategies are supported: inject-magic-state and auto-corrected. Related prior work on qec.ppr began in #1486 #1563 #1580.
Description of the Change:
- New operation:
qec.select.ppm– conditional Pauli product measurement based on a boolean control - New operation:
qec.prepare– prepares logical qubits in a specified initial state (|0⟩, |1⟩, |+⟩, |-⟩, |Y⟩, |-Y⟩, |m⟩, or |m̅⟩) - Extended
qec.pprandqec.ppmto support conditional execution - Implemented decomposition strategies:
inject-magic-stateandauto-corrected.
Example: Input:
func.func @test_ppr_to_ppm(%q1 : !quantum.bit) {
%0 = qec.ppr ["Z"](8) %q1 : !quantum.bit
return
}
Run:
$ quantum-opt --ppr_to_ppm='decompose-method=auto-corrected' test.mlir
Outputs:
module {
func.func @foo(%arg0: !quantum.bit) {
%c2_i64 = arith.constant 2 : i64
%0 = quantum.alloc(%c2_i64) : !quantum.reg
%1 = quantum.extract %0[ 0] : !quantum.reg -> !quantum.bit
%2 = quantum.extract %0[ 1] : !quantum.reg -> !quantum.bit
%3 = qec.prepare zero %1 : !quantum.bit
%4 = qec.prepare magic %2 : !quantum.bit
%mres, %out_qubits:2 = qec.ppm ["Z", "Z"] %arg0, %4 : !quantum.bit, !quantum.bit
%mres_0, %out_qubits_1:2 = qec.ppm ["Z", "Y"] %3, %out_qubits#1 : !quantum.bit, !quantum.bit
%mres_2, %out_qubits_3 = qec.ppm ["X"] %out_qubits_1#1 : !quantum.bit
%mres_4, %out_qubits_5 = qec.select.ppm(%mres, ["X"], ["Z"]) %out_qubits_1#0 : !quantum.bit
%5 = arith.xori %mres_0, %mres_2 : i1
%6 = qec.ppr ["Z"](2) %out_qubits#0 cond(%5) : !quantum.bit
quantum.dealloc %0 : !quantum.reg
return
}
}
Run:
$ quantum-opt --ppr_to_ppm='decompose-method=inject-magic-state' test.mlir
Outputs:
module {
func.func @foo(%arg0: !quantum.bit) {
%c2_i64 = arith.constant 2 : i64
%0 = quantum.alloc(%c2_i64) : !quantum.reg
%1 = quantum.extract %0[ 0] : !quantum.reg -> !quantum.bit
%2 = qec.prepare magic %1 : !quantum.bit
%mres, %out_qubits:2 = qec.ppm ["Z", "Z"] %arg0, %2 : !quantum.bit, !quantum.bit
%3 = quantum.extract %0[ 1] : !quantum.reg -> !quantum.bit
%4 = qec.prepare zero %3 : !quantum.bit
%mres_0, %out_qubits_1:2 = qec.ppm ["Z", "Y"](-1) %out_qubits#0, %4 cond(%mres) : !quantum.bit, !quantum.bit
%mres_2, %out_qubits_3 = qec.ppm ["X"] %out_qubits_1#1 cond(%mres) : !quantum.bit
%5 = arith.xori %mres_0, %mres_2 : i1
%6 = qec.ppr ["Z"](2) %out_qubits_1#0 cond(%5) : !quantum.bit
%mres_4, %out_qubits_5 = qec.ppm ["X"] %out_qubits#1 : !quantum.bit
%7 = qec.ppr ["Z"](2) %6 cond(%mres_4) : !quantum.bit
quantum.dealloc %0 : !quantum.reg
return
}
}
[sc-89168]