Skip to content

🎨 [NA] Add 2Q-Gate Layer to Decomposer Interface#976

Open
ystade wants to merge 6 commits intomainfrom
ystade/decomposer-interface
Open

🎨 [NA] Add 2Q-Gate Layer to Decomposer Interface#976
ystade wants to merge 6 commits intomainfrom
ystade/decomposer-interface

Conversation

@ystade
Copy link
Copy Markdown
Collaborator

@ystade ystade commented Apr 3, 2026

Description

We are implementing an actual decomposer, replacing the current NoOpDecomposer. Because this new Decomposer has an optimzation routine that also affects the two-qubit gates, the decomposer must be able to modify the two-qubit gates. Additionally, one could imagine, that the decomposer might also transform two-qubit gates.

Checklist

  • The pull request only contains commits that are focused and relevant to this change.
  • I have added appropriate tests that cover the new/changed functionality.
  • I have updated the documentation to reflect these changes.
  • I have added entries to the changelog for any noteworthy additions, changes, fixes, or removals.
  • I have added migration instructions to the upgrade guide (if needed).
  • The changes follow the project's style guidelines and introduce no new warnings.
  • The changes are fully tested and pass the CI checks.
  • I have reviewed my own code changes.

If PR contains AI-assisted content:

  • I have disclosed the use of AI tools in the PR description as per our AI Usage Guidelines.
  • AI-assisted commits include an Assisted-by: [Model Name] via [Tool Name] footer.
  • I confirm that I have personally reviewed and understood all AI-generated content, and accept full responsibility for it.

@ystade ystade added this to the Neutral Atom Compilation milestone Apr 3, 2026
@ystade ystade self-assigned this Apr 3, 2026
@ystade ystade added c++ Anything related to C++ code enhancement Anything related to improvements of the existing library refactor Anything related to code refactoring labels Apr 3, 2026
@github-project-automation github-project-automation Bot moved this to In Progress in MQT Compilation Apr 3, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 3, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 85160aa1-db9f-4f39-91db-778b20880c0e

📥 Commits

Reviewing files that changed from the base of the PR and between 864d34f and 97e29fa.

📒 Files selected for processing (1)
  • include/na/zoned/decomposer/DecomposerBase.hpp

📝 Walkthrough

Summary by CodeRabbit

  • Refactor
    • Compiler now decomposes single‑ and two‑qubit gate layers together; downstream steps consume the decomposed two‑qubit layers while timing/statistics continue to use decomposed single‑qubit layers.
  • Chore
    • Changelog updated to note the decomposer interface change for zoned neutral‑atom compilation.

Walkthrough

Compiler and decomposer interfaces updated so the decomposer accepts both single‑qubit and two‑qubit gate layer inputs and returns decomposed single‑ and two‑qubit layers; compiler pipeline, reuse analysis, and layout synthesis now consume the decomposed two‑qubit layers.

Changes

Cohort / File(s) Summary
Decomposer Base Abstraction
include/na/zoned/decomposer/DecomposerBase.hpp
Changed virtual decompose(...) signature to accept singleQubitGateLayers and twoQubitGateLayers, and to return std::pair<std::vector<SingleQubitGateLayer>, std::vector<TwoQubitGateLayer>>.
NoOpDecomposer Implementation
include/na/zoned/decomposer/NoOpDecomposer.hpp, src/na/zoned/decomposer/NoOpDecomposer.cpp
Override updated to new signature; implementation now returns a pair of decomposed single‑qubit layers and the provided two‑qubit layers (passthrough for two‑qubit layers).
Compiler Pipeline
include/na/zoned/Compiler.hpp
Call site updated to pass both single‑ and two‑qubit layers into decompose(...); destructures returned pair into decomposedSingleQubitGateLayers and decomposedTwoQubitGateLayers; reuse analysis and layout synthesis now use decomposedTwoQubitGateLayers.
Changelog
CHANGELOG.md
Added entry documenting the decomposer interface change (two‑qubit layer addition).

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Compiler
    participant Decomposer
    participant ReuseAnalyzer

    Client->>Compiler: compile(zoned circuit)
    Compiler->>Decomposer: decompose(singleQubitGateLayers, twoQubitGateLayers)
    Decomposer-->>Compiler: (decomposedSingleQubitGateLayers, decomposedTwoQubitGateLayers)
    Compiler->>ReuseAnalyzer: analyze(decomposedTwoQubitGateLayers)
    ReuseAnalyzer-->>Compiler: reuse decisions
    Compiler-->>Client: compiled output
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • burgholzer

Poem

🐇 I hop through circuits, bright and true,
I split the gates — both one and two.
Side by side they come back home,
Decomposed and ready, no more to roam.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: adding two-qubit gate layer support to the decomposer interface.
Description check ✅ Passed The description explains the motivation (new decomposer needs to modify 2Q gates) and most checklist items are completed, though upgrade guide migration is marked unchecked.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ystade/decomposer-interface

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
include/na/zoned/Compiler.hpp (1)

217-228: ⚠️ Potential issue | 🟠 Major

Inconsistent usage of original vs. decomposed two-qubit gate layers.

Line 217 passes decomposedTwoQubitGateLayers to analyzeReuse, but line 228 passes the original twoQubitGateLayers to synthesize. When a real decomposer that modifies 2Q gates is introduced (as mentioned in the PR objectives), this inconsistency will cause the reuse analysis and layout synthesis to operate on different gate sets, likely leading to incorrect compilation results.

Should line 228 also use decomposedTwoQubitGateLayers?

Proposed fix
     const auto& [placement, routing] = LayoutSynthesizer::synthesize(
-        qComp.getNqubits(), twoQubitGateLayers, reuseQubits);
+        qComp.getNqubits(), decomposedTwoQubitGateLayers, reuseQubits);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@include/na/zoned/Compiler.hpp` around lines 217 - 228, The reuse analysis is
run on decomposedTwoQubitGateLayers via SELF.analyzeReuse but
LayoutSynthesizer::synthesize is called with the original twoQubitGateLayers,
causing inconsistent inputs; change the call to LayoutSynthesizer::synthesize to
pass decomposedTwoQubitGateLayers (along with qComp.getNqubits() and
reuseQubits) so layout synthesis uses the same decomposed gate set as
analyzeReuse.
include/na/zoned/decomposer/DecomposerBase.hpp (1)

25-35: 🧹 Nitpick | 🔵 Trivial

Incomplete documentation for the updated interface.

The docstring is missing @param twoQubitGateLayers and the @return description needs to reflect that a pair is now returned (including both decomposed single-qubit and two-qubit gate layers).

Proposed documentation update
   /**
    * This function defines the interface of the decomposer.
    * `@param` singleQubitGateLayers are the layers of single-qubit gates that are
    * meant to be first decomposed into the native gate set.
-   * `@return` the new single-qubit gate layers
+   * `@param` twoQubitGateLayers are the layers of two-qubit gates that may be
+   * transformed by the decomposer.
+   * `@return` a pair containing the decomposed single-qubit gate layers and
+   * the (potentially transformed) two-qubit gate layers.
    */
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@include/na/zoned/decomposer/DecomposerBase.hpp` around lines 25 - 35, The
method documentation for DecomposerBase::decompose is out of date: add a `@param`
entry for twoQubitGateLayers and update `@return` to describe that the function
returns a std::pair containing the decomposed single-qubit gate layers and the
decomposed two-qubit gate layers. Locate the decompose(...) declaration and
expand the comment block to include "@param twoQubitGateLayers the layers of
two-qubit gates to be considered during decomposition" and update "@return" to
clearly state that it returns a pair<std::vector<SingleQubitGateLayer>,
std::vector<TwoQubitGateLayer>> representing the new single-qubit and two-qubit
gate layers respectively.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@include/na/zoned/Compiler.hpp`:
- Around line 217-228: The reuse analysis is run on decomposedTwoQubitGateLayers
via SELF.analyzeReuse but LayoutSynthesizer::synthesize is called with the
original twoQubitGateLayers, causing inconsistent inputs; change the call to
LayoutSynthesizer::synthesize to pass decomposedTwoQubitGateLayers (along with
qComp.getNqubits() and reuseQubits) so layout synthesis uses the same decomposed
gate set as analyzeReuse.

In `@include/na/zoned/decomposer/DecomposerBase.hpp`:
- Around line 25-35: The method documentation for DecomposerBase::decompose is
out of date: add a `@param` entry for twoQubitGateLayers and update `@return` to
describe that the function returns a std::pair containing the decomposed
single-qubit gate layers and the decomposed two-qubit gate layers. Locate the
decompose(...) declaration and expand the comment block to include "@param
twoQubitGateLayers the layers of two-qubit gates to be considered during
decomposition" and update "@return" to clearly state that it returns a
pair<std::vector<SingleQubitGateLayer>, std::vector<TwoQubitGateLayer>>
representing the new single-qubit and two-qubit gate layers respectively.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: b7d49d0c-42a4-47b4-9b6e-fe5fffd4b555

📥 Commits

Reviewing files that changed from the base of the PR and between a88b72e and dbadb35.

📒 Files selected for processing (4)
  • include/na/zoned/Compiler.hpp
  • include/na/zoned/decomposer/DecomposerBase.hpp
  • include/na/zoned/decomposer/NoOpDecomposer.hpp
  • src/na/zoned/decomposer/NoOpDecomposer.cpp

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 3, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@CHANGELOG.md`:
- Around line 14-17: Add an UPGRADING.md entry under the [Unreleased] section
documenting the breaking change to the DecomposerBase interface: the decompose()
method now accepts an additional twoQubitGateLayers parameter and its return
type changed to std::pair; instruct maintainers to update any custom
DecomposerBase subclasses by adding the new parameter to their decompose()
implementations, returning the new std::pair form (describe both elements of the
pair), and provide a short example/migration snippet showing the old
signature->new signature mapping and how to construct the std::pair result for
compatibility.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: fe22c2ff-05f1-4bc8-bbc1-51b56b8c9d38

📥 Commits

Reviewing files that changed from the base of the PR and between dbadb35 and d770ac8.

📒 Files selected for processing (1)
  • CHANGELOG.md

Comment thread CHANGELOG.md
@ystade ystade enabled auto-merge (squash) April 4, 2026 08:10
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@include/na/zoned/decomposer/DecomposerBase.hpp`:
- Around line 27-40: The decompose() API currently returns an unnamed std::pair
which makes the contract (which element is the single-qubit layers vs two-qubit
layers) implicit and error-prone; define a named return type (e.g., struct
DecompositionResult { std::vector<SingleQubitGateLayer> singleQubitLayers;
std::vector<TwoQubitGateLayer> twoQubitLayers; }) and update
DecomposerBase::decompose signature to return DecompositionResult (and update
the comment to explicitly state which member maps to generate() and which maps
to analyzeReuse()/synthesize()), then adjust any callers to use the named fields
instead of std::pair::first/second.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 62fb42dd-dc97-4917-a328-82e6fa44e6e8

📥 Commits

Reviewing files that changed from the base of the PR and between d770ac8 and 864d34f.

📒 Files selected for processing (2)
  • include/na/zoned/Compiler.hpp
  • include/na/zoned/decomposer/DecomposerBase.hpp

Comment on lines +27 to +40
*
* The decomposer may change the layering produced by the scheduler and,
* hence, it receives the single-qubit and two-qubit gate layers.
* @param singleQubitGateLayers are the layers of single-qubit gates that are
* meant to be first decomposed into the native gate set.
* @return the new single-qubit gate layers
* @param twoQubitGateLayers are the layers of two-qubit gates that the
* decomposer may change.
* @return a new pair of single-qubit and two-qubit gate layers
*/
[[nodiscard]] virtual auto decompose(
const std::vector<SingleQubitGateRefLayer>& singleQubitGateLayers) const
-> std::vector<SingleQubitGateLayer> = 0;
[[nodiscard]] virtual auto
decompose(const std::vector<SingleQubitGateRefLayer>& singleQubitGateLayers,
const std::vector<TwoQubitGateLayer>& twoQubitGateLayers) const
-> std::pair<std::vector<SingleQubitGateLayer>,
std::vector<TwoQubitGateLayer>> = 0;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Make the new decomposition result contract explicit.

The compiler now feeds the returned 2Q layers into analyzeReuse()/synthesize() and the returned 1Q layers into generate(). A raw std::pair plus the current doc leaves the required alignment invariant implicit; documenting it here, or wrapping it in a named DecompositionResult, would make future decomposers harder to misuse.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@include/na/zoned/decomposer/DecomposerBase.hpp` around lines 27 - 40, The
decompose() API currently returns an unnamed std::pair which makes the contract
(which element is the single-qubit layers vs two-qubit layers) implicit and
error-prone; define a named return type (e.g., struct DecompositionResult {
std::vector<SingleQubitGateLayer> singleQubitLayers;
std::vector<TwoQubitGateLayer> twoQubitLayers; }) and update
DecomposerBase::decompose signature to return DecompositionResult (and update
the comment to explicitly state which member maps to generate() and which maps
to analyzeReuse()/synthesize()), then adjust any callers to use the named fields
instead of std::pair::first/second.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c++ Anything related to C++ code enhancement Anything related to improvements of the existing library refactor Anything related to code refactoring

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants