Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ This project adheres to [Semantic Versioning], with the exception that minor rel

_If you are upgrading: please see [`UPGRADING.md`](UPGRADING.md#unreleased)._

### Changed

- 🎨 Add two-qubit gate layer to decomposer interface in zoned neutral atom compiler ([#976]) ([**@ystade**])

Comment thread
ystade marked this conversation as resolved.
### Fixed

- 🐛 Fix condition to detect previously unrecognized reuse opportunities ([#953]) ([**@ystade**])
Expand Down Expand Up @@ -200,6 +204,7 @@ _📚 Refer to the [GitHub Release Notes] for previous changelogs._

<!-- PR links -->

[#976]: https://github.com/munich-quantum-toolkit/qmap/pull/976
[#953]: https://github.com/munich-quantum-toolkit/qmap/pull/953
[#924]: https://github.com/munich-quantum-toolkit/qmap/pull/924
[#921]: https://github.com/munich-quantum-toolkit/qmap/pull/921
Expand Down
9 changes: 5 additions & 4 deletions include/na/zoned/Compiler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -202,8 +202,9 @@ class Compiler : protected Scheduler,

SPDLOG_DEBUG("Decomposing...");
const auto decomposingStart = std::chrono::system_clock::now();
const auto& decomposedSingleQubitGateLayers =
SELF.decompose(singleQubitGateLayers);
const auto& [decomposedSingleQubitGateLayers,
decomposedTwoQubitGateLayers] =
SELF.decompose(singleQubitGateLayers, twoQubitGateLayers);
const auto decomposingEnd = std::chrono::system_clock::now();
statistics_.decomposingTime =
std::chrono::duration_cast<std::chrono::microseconds>(decomposingEnd -
Expand All @@ -213,7 +214,7 @@ class Compiler : protected Scheduler,

SPDLOG_DEBUG("Analyzing reuse...");
const auto reuseAnalysisStart = std::chrono::system_clock::now();
const auto& reuseQubits = SELF.analyzeReuse(twoQubitGateLayers);
const auto& reuseQubits = SELF.analyzeReuse(decomposedTwoQubitGateLayers);
const auto reuseAnalysisEnd = std::chrono::system_clock::now();
statistics_.reuseAnalysisTime =
std::chrono::duration_cast<std::chrono::microseconds>(
Expand All @@ -224,7 +225,7 @@ class Compiler : protected Scheduler,
SPDLOG_DEBUG("Synthesizing layout...");
const auto layoutSynthesisStart = std::chrono::system_clock::now();
const auto& [placement, routing] = LayoutSynthesizer::synthesize(
qComp.getNqubits(), twoQubitGateLayers, reuseQubits);
qComp.getNqubits(), decomposedTwoQubitGateLayers, reuseQubits);
const auto layoutSynthesisEnd = std::chrono::system_clock::now();
statistics_.layoutSynthesisTime =
std::chrono::duration_cast<std::chrono::microseconds>(
Expand Down
18 changes: 14 additions & 4 deletions include/na/zoned/decomposer/DecomposerBase.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,22 @@ class DecomposerBase {
virtual ~DecomposerBase() = default;
/**
* This function defines the interface of the decomposer.
*
* 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. This pair
* replaces the pair of single-qubit and two-qubit gate layers returned from
* the scheduler. There is always one single-qubit gate layer more than
* 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;
Comment on lines +27 to +43
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.

};
} // namespace na::zoned
8 changes: 5 additions & 3 deletions include/na/zoned/decomposer/NoOpDecomposer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,10 @@ class NoOpDecomposer : public DecomposerBase {
NoOpDecomposer(const Architecture& /* unused */, const Config& /* unused */) {
}

[[nodiscard]] auto decompose(
const std::vector<SingleQubitGateRefLayer>& singleQubitGateLayers) const
-> std::vector<SingleQubitGateLayer> override;
[[nodiscard]] auto
decompose(const std::vector<SingleQubitGateRefLayer>& singleQubitGateLayers,
const std::vector<TwoQubitGateLayer>& twoQubitGateLayers) const
-> std::pair<std::vector<SingleQubitGateLayer>,
std::vector<TwoQubitGateLayer>> override;
};
} // namespace na::zoned
8 changes: 5 additions & 3 deletions src/na/zoned/decomposer/NoOpDecomposer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@

namespace na::zoned {
auto NoOpDecomposer::decompose(
const std::vector<SingleQubitGateRefLayer>& singleQubitGateLayers) const
-> std::vector<SingleQubitGateLayer> {
const std::vector<SingleQubitGateRefLayer>& singleQubitGateLayers,
const std::vector<TwoQubitGateLayer>& twoQubitGateLayers) const
-> std::pair<std::vector<SingleQubitGateLayer>,
std::vector<TwoQubitGateLayer>> {
std::vector<SingleQubitGateLayer> result;
result.reserve(singleQubitGateLayers.size());
for (const auto& layer : singleQubitGateLayers) {
Expand All @@ -30,6 +32,6 @@ auto NoOpDecomposer::decompose(
}
result.emplace_back(std::move(newLayer));
}
return result;
return {std::move(result), twoQubitGateLayers};
}
} // namespace na::zoned
Loading