Skip to content

Implement a decomposition of PPRs into PPMs #1664

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 45 commits into from
May 20, 2025
Merged

Implement a decomposition of PPRs into PPMs #1664

merged 45 commits into from
May 20, 2025

Conversation

sengthai
Copy link
Contributor

@sengthai sengthai commented Apr 16, 2025

Context:
This PR introduces a new pass that decomposes 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 --decompose_clifford_ppr='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 --decompose_clifford_ppr='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]
[sc-90158]

@sengthai sengthai marked this pull request as ready for review April 24, 2025 12:57
@sengthai sengthai changed the title [WIP] Implement a decomposition of non-Clifford PPRs into PPMs Implement a decomposition of non-Clifford PPRs into PPMs Apr 24, 2025
@sengthai sengthai requested a review from a team April 24, 2025 12:57
@sengthai sengthai added enhancement New feature or request do-not-merge labels Apr 24, 2025
@sengthai

This comment was marked as resolved.

This comment was marked as outdated.

@sengthai sengthai changed the title Implement a decomposition of non-Clifford PPRs into PPMs Implement a decomposition of PPRs into PPMs Apr 29, 2025
@dime10 dime10 self-requested a review May 1, 2025 22:17
Copy link
Contributor

@dime10 dime10 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work!! :) So far I'm leaving some comments regarding organization, documentation, naming, etc. I will leave a second review regarding the C++ implementation tomorrow :)

sengthai and others added 2 commits May 7, 2025 10:45
Co-authored-by: David Ittah <[email protected]>
sengthai added 3 commits May 15, 2025 11:45
Updated docstring reference in `DecomposeNonCliffordPPR`.
…tate preparation rules.

Added verification logic to enforce these rules.
@sengthai sengthai force-pushed the ppr-to-ppm branch 2 times, most recently from 5a2b393 to 19b42d3 Compare May 15, 2025 19:59
@sengthai sengthai requested review from isaacdevlugt and dime10 May 15, 2025 20:56
@sengthai sengthai force-pushed the ppr-to-ppm branch 2 times, most recently from 1d12842 to 2ad7e59 Compare May 15, 2025 21:24
Copy link
Contributor

@dime10 dime10 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Love the code, it's so clean 😍

@dime10
Copy link
Contributor

dime10 commented May 20, 2025

@isaacdevlugt can you change your review? Nvm, Isaac is on vacation.

@dime10 dime10 dismissed isaacdevlugt’s stale review May 20, 2025 19:50

reviewer is unavailable

@sengthai
Copy link
Contributor Author

@isaacdevlugt can you change your review? Nvm, Isaac is on vacation.

Also, it is still possible to review this PR in to_ppm pass #1750 as well.

@dime10 dime10 merged commit 090f56a into main May 20, 2025
39 checks passed
@dime10 dime10 deleted the ppr-to-ppm branch May 20, 2025 22:33
sengthai added a commit that referenced this pull request May 29, 2025
…#1750)

**Context:**
Introduced the `ppm_compilation` pass as a top-level composition of
existing transformation and optimization passes. This allows users to
apply the transformation Clifford+T to Pauli product measurements (PPMs)
in a single step without managing sub-pass sequencing manually.
 
The sub-paseses comprise:
* `to_ppr`: Converts gates into Pauli Product Rotations (PPRs)
(Transformation)
       #1486  
       #1499 
  * `commute_ppr`: Commutes PPRs past non-Clifford PPRs (Optimization)
      #1563
  * `merge_ppr_ppm`: Merges PPRs into PPMs (Optimization) 
      #1580 
  * `ppr_to_ppm`: Decomposes PPRs into PPMs (Transformation) 
      #1664 

**Example:**
```python
  import pennylane as qml
  from catalyst import measure, passes, qjit
  
  pipe = [("pipe", ["enforce-runtime-invariants-pipeline"])]
  
  @qjit(pipelines=pipe, target="mlir")
  @passes.ppm_compilation(decompose_method="auto-corrected", avoid_y_measure=True, max_pauli_size=2)
  @qml.qnode(qml.device("null.qubit", wires=2))
  def circuit():
      qml.CNOT([0, 1])
      qml.CNOT([1, 0])
      qml.adjoint(qml.T)(0)
      qml.T(1)
      return measure(0), measure(1)
  
  print(circuit.mlir_opt)
```

**Benefits:**
- Simplifies the user workflow for compilation.

[[sc-90149]]

---------

Co-authored-by: Josh Izaac <[email protected]>
Co-authored-by: David Ittah <[email protected]>
Co-authored-by: Joey Carter <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants