catalyst icon indicating copy to clipboard operation
catalyst copied to clipboard

Implement a decomposition of non-Clifford PPRs into PPMs

Open sengthai opened this issue 6 months ago • 3 comments

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.ppr and qec.ppm to support conditional execution
  • Implemented decomposition strategies: inject-magic-state and auto-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]

sengthai avatar Apr 16 '25 22:04 sengthai