Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
c20a742
✨ Add max filling factor
ystade Nov 27, 2025
1620370
✅ Add test for added behaviour
ystade Nov 27, 2025
ec0d8e8
Apply suggestions from code review
ystade Nov 27, 2025
c69f26e
🎨 pre-commit fixes
pre-commit-ci[bot] Nov 27, 2025
0252833
🎨 Remove leftover
ystade Nov 27, 2025
c94ac78
🎨 Fix missing parking offset
ystade Nov 27, 2025
5ee5b7c
🎨 Fix type conversion bug on windows
ystade Nov 28, 2025
708d11d
✅ Increase test coverage
ystade Nov 28, 2025
6dfb970
Merge branch 'main' into ystade/max-filling-factor
ystade Nov 28, 2025
a8c042c
📝 Add changelog entry
ystade Nov 28, 2025
61688dd
✨ Enable relaxed rearrangements in code-generator
ystade Nov 28, 2025
77e2fbc
✅ Adapt tests
ystade Nov 28, 2025
9a05354
✅ Fix tests
ystade Nov 28, 2025
03d2c8c
💚 Fix clang-tidy warnings
ystade Nov 28, 2025
064eef4
🐛 Fix compilation bug on old mac OS
ystade Nov 28, 2025
aad203b
✅ Try increase test coverage
ystade Nov 28, 2025
4936455
🐛 Fix bug
ystade Dec 1, 2025
97c60a5
🐛 Fix missing constructor bug
ystade Dec 1, 2025
fc8a2d9
🐛 Fix logical bug
ystade Dec 1, 2025
40c596f
✅ Add test for better coverage
ystade Dec 1, 2025
068f659
Merge remote-tracking branch 'origin/main' into ystade/relaxed-code-g…
ystade Dec 1, 2025
3e7c7bc
🎨 Some fixes/improvements
ystade Dec 1, 2025
1353fc4
📝 Update changelog
ystade Dec 1, 2025
4890a6d
🎨 Fix enumerate for rvalues
ystade Dec 3, 2025
a7e891c
🎨 Add Upgrading note
ystade Dec 3, 2025
18ef464
🎨 Implement relaxed router
ystade Dec 3, 2025
5fceb33
Merge remote-tracking branch 'origin/main' into ystade/relaxed-router
ystade Dec 3, 2025
16ec923
🎨 Remove references from chrono variable
ystade Dec 4, 2025
2d46808
📝 Add docstrings
ystade Dec 4, 2025
1740419
📝 Add docstring
ystade Dec 4, 2025
362bee6
🎨 Make function static
ystade Dec 4, 2025
9575f66
🎨 More readable alternative
ystade Dec 4, 2025
c4e58a9
📝 Add addtional comment
ystade Dec 4, 2025
00a4121
🔧 Add missing config option
ystade Dec 4, 2025
1eac09f
🎨 Improve platform compatibility
ystade Dec 4, 2025
85212ba
🎨 Add override annotations
ystade Dec 5, 2025
d19af9a
🎨 Fix minor bug
ystade Dec 5, 2025
013801f
📝 Refine docstring
ystade Dec 5, 2025
b80464f
📝 Correct docstring
ystade Dec 5, 2025
4b440b8
📝 Fix comment
ystade Dec 5, 2025
e5db010
Merge remote-tracking branch 'origin/main' into ystade/relaxed-router
ystade Dec 5, 2025
98d1bd0
🎨 Combine both routers
ystade Dec 5, 2025
a9f018d
🎨 Adapt test suite and fix bugs
ystade Dec 5, 2025
309194a
🎨 Fix docstring
ystade Dec 5, 2025
7e5feaf
🎨 Fix strict router
ystade Dec 5, 2025
ba19512
🎨 Fix json parsing
ystade Dec 5, 2025
f722105
🎨 Expose routing method
ystade Dec 5, 2025
b1379bd
🎨 Adopt python inteface file
ystade Dec 5, 2025
3edebd7
💚 Add missing header
ystade Dec 5, 2025
de7ef5e
📝 Fix docstrings
ystade Dec 5, 2025
b556d1b
🎨 Refactor code
ystade Dec 5, 2025
2b53107
📝 Update changelog
ystade Dec 5, 2025
17fbb32
📝 Make docstring more comprehensible
ystade Dec 5, 2025
41eb559
📝 Fix changelog
ystade Dec 5, 2025
5f07b8d
🎨 Avoid overflow
ystade Dec 5, 2025
4684fb1
🎨 Split routing function
ystade Dec 5, 2025
f3e4399
⚡️ Micro optimization
ystade Dec 6, 2025
342b89d
💚 Add missing headers
ystade Dec 6, 2025
a102c6b
📝 Make docstrings more precise
ystade Dec 6, 2025
b617658
📝 Mention preferSPlit parameter
ystade Dec 6, 2025
837b393
⚡️ Improve performance
ystade Dec 6, 2025
d35f58d
📝 Provide defaults andd improve docstring
ystade Dec 6, 2025
d301fd3
📝 Improve docstring
ystade Dec 6, 2025
3b7c22c
Merge branch 'main' into ystade/relaxed-router
ystade Dec 6, 2025
039797b
🐛 Fix docstring and ordering of atoms to route
ystade Dec 6, 2025
01fee79
Merge remote-tracking branch 'origin/main' into ystade/relaxed-router
ystade Dec 6, 2025
a9274c7
📝 Improve docstrings
ystade Dec 8, 2025
1de1a75
Merge remote-tracking branch 'origin/main' into ystade/relaxed-router
ystade Dec 8, 2025
fb88af1
🎨 Micro opt
ystade Dec 8, 2025
37006fa
🎨 Remove leftovers from parking_offset
ystade Dec 9, 2025
122fe45
🎨 Expose prefer_split
ystade Dec 9, 2025
ff1bb53
🐛 Fix pyi file
ystade Dec 11, 2025
ac91302
🎨 Apply coderabbit's suggestion
ystade Dec 11, 2025
0b02d53
📝 Improve docstring
ystade Dec 11, 2025
99a30ed
Merge remote-tracking branch 'origin/main' into ystade/relaxed-router
ystade Dec 11, 2025
747195e
Revert "🎨 Apply coderabbit's suggestion"
ystade Dec 11, 2025
c9546bd
🚚 Rename variable for clarity
ystade Dec 11, 2025
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)._

### Added

- ✨ Add relaxed routing method to the zoned neutral atom compiler ([#859]) ([**@ystade**])

### Changed

- 👷 Stop testing on `ubuntu-22.04` and `ubuntu-22.04-arm` runners ([#874]) ([**@denialhaag**])
Expand Down Expand Up @@ -169,6 +173,7 @@ _📚 Refer to the [GitHub Release Notes] for previous changelogs._
<!-- PR links -->

[#874]: https://github.com/munich-quantum-toolkit/qmap/pull/874
[#859]: https://github.com/munich-quantum-toolkit/qmap/pull/859
[#848]: https://github.com/munich-quantum-toolkit/qmap/pull/848
[#847]: https://github.com/munich-quantum-toolkit/qmap/pull/847
[#832]: https://github.com/munich-quantum-toolkit/qmap/pull/832
Expand Down
37 changes: 34 additions & 3 deletions bindings/na/zoned/zoned.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "na/zoned/layout_synthesizer/PlaceAndRouteSynthesizer.hpp"
#include "na/zoned/layout_synthesizer/placer/AStarPlacer.hpp"
#include "na/zoned/layout_synthesizer/placer/VertexMatchingPlacer.hpp"
#include "na/zoned/layout_synthesizer/router/IndependentSetRouter.hpp"

#include <cstddef>
// The header <nlohmann/json.hpp> is used, but clang-tidy confuses it with the
Expand All @@ -24,6 +25,7 @@
#include <pybind11/attr.h>
#include <pybind11/cast.h>
#include <pybind11/detail/common.h>
#include <pybind11/native_enum.h>
#include <pybind11/pybind11.h>
// NOLINTNEXTLINE(misc-include-cleaner)
#include <pybind11_json/pybind11_json.hpp>
Expand Down Expand Up @@ -51,6 +53,17 @@ PYBIND11_MODULE(MQT_QMAP_MODULE_NAME, m, py::mod_gil_not_used()) {
return self.exportNAVizMachine();
});

//===--------------------------------------------------------------------===//
// Routing Method Enum
//===--------------------------------------------------------------------===//
py::native_enum<na::zoned::IndependentSetRouter::Config::Method>(
m, "RoutingMethod", "enum.Enum")
.value("strict", na::zoned::IndependentSetRouter::Config::Method::STRICT)
.value("relaxed",
na::zoned::IndependentSetRouter::Config::Method::RELAXED)
.export_values()
.finalize();

//===--------------------------------------------------------------------===//
// Routing-agnostic Compiler
//===--------------------------------------------------------------------===//
Expand All @@ -63,7 +76,9 @@ PYBIND11_MODULE(MQT_QMAP_MODULE_NAME, m, py::mod_gil_not_used()) {
const std::string& logLevel, const double maxFillingFactor,
const bool useWindow, const size_t windowSize,
const bool dynamicPlacement,
const bool warnUnsupportedGates)
const na::zoned::IndependentSetRouter::Config::Method
routingMethod,
const double preferSplit, const bool warnUnsupportedGates)
-> na::zoned::RoutingAgnosticCompiler {
na::zoned::RoutingAgnosticCompiler::Config config;
config.logLevel = spdlog::level::from_str(logLevel);
Expand All @@ -72,6 +87,8 @@ PYBIND11_MODULE(MQT_QMAP_MODULE_NAME, m, py::mod_gil_not_used()) {
.useWindow = useWindow,
.windowSize = windowSize,
.dynamicPlacement = dynamicPlacement};
config.layoutSynthesizerConfig.routerConfig = {
.method = routingMethod, .preferSplit = preferSplit};
config.codeGeneratorConfig = {.warnUnsupportedGates =
warnUnsupportedGates};
return {arch, config};
Expand All @@ -85,6 +102,10 @@ PYBIND11_MODULE(MQT_QMAP_MODULE_NAME, m, py::mod_gil_not_used()) {
defaultConfig.layoutSynthesizerConfig.placerConfig.windowSize,
"dynamic_placement"_a =
defaultConfig.layoutSynthesizerConfig.placerConfig.dynamicPlacement,
"routing_method"_a =
defaultConfig.layoutSynthesizerConfig.routerConfig.method,
"prefer_split"_a =
defaultConfig.layoutSynthesizerConfig.routerConfig.preferSplit,
"warn_unsupported_gates"_a =
defaultConfig.codeGeneratorConfig.warnUnsupportedGates);
}
Expand Down Expand Up @@ -125,7 +146,10 @@ PYBIND11_MODULE(MQT_QMAP_MODULE_NAME, m, py::mod_gil_not_used()) {
const double windowRatio, const double windowShare,
const float deepeningFactor, const float deepeningValue,
const float lookaheadFactor, const float reuseLevel,
const size_t maxNodes, const bool warnUnsupportedGates)
const size_t maxNodes,
const na::zoned::IndependentSetRouter::Config::Method
routingMethod,
const double preferSplit, const bool warnUnsupportedGates)
-> na::zoned::RoutingAwareCompiler {
na::zoned::RoutingAwareCompiler::Config config;
config.logLevel = spdlog::level::from_str(logLevel);
Expand All @@ -139,7 +163,10 @@ PYBIND11_MODULE(MQT_QMAP_MODULE_NAME, m, py::mod_gil_not_used()) {
.deepeningValue = deepeningValue,
.lookaheadFactor = lookaheadFactor,
.reuseLevel = reuseLevel,
.maxNodes = maxNodes};
.maxNodes = maxNodes,
};
config.layoutSynthesizerConfig.routerConfig = {
.method = routingMethod, .preferSplit = preferSplit};
config.codeGeneratorConfig = {.warnUnsupportedGates =
warnUnsupportedGates};
return {arch, config};
Expand All @@ -165,6 +192,10 @@ PYBIND11_MODULE(MQT_QMAP_MODULE_NAME, m, py::mod_gil_not_used()) {
defaultConfig.layoutSynthesizerConfig.placerConfig.reuseLevel,
"max_nodes"_a =
defaultConfig.layoutSynthesizerConfig.placerConfig.maxNodes,
"routing_method"_a =
defaultConfig.layoutSynthesizerConfig.routerConfig.method,
"prefer_split"_a =
defaultConfig.layoutSynthesizerConfig.routerConfig.preferSplit,
"warn_unsupported_gates"_a =
defaultConfig.codeGeneratorConfig.warnUnsupportedGates);
}
Expand Down
46 changes: 28 additions & 18 deletions include/na/zoned/Compiler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,23 +159,14 @@ class Compiler : protected Scheduler,
}
#endif // SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_DEBUG

const auto& schedulingStart = std::chrono::system_clock::now();
// CodeQL was not very happy about the structural binding here, hence I
// removed it.
SPDLOG_DEBUG("Scheduling...");
const auto schedulingStart = std::chrono::system_clock::now();
const auto& schedule = SELF.schedule(qComp);
const auto schedulingEnd = std::chrono::system_clock::now();
const auto& singleQubitGateLayers = schedule.first;
const auto& twoQubitGateLayers = schedule.second;
const auto& schedulingEnd = std::chrono::system_clock::now();
const auto& reuseQubits = SELF.analyzeReuse(twoQubitGateLayers);
const auto& reuseAnalysisEnd = std::chrono::system_clock::now();
const auto& [placement, routing] = LayoutSynthesizer::synthesize(
qComp.getNqubits(), twoQubitGateLayers, reuseQubits);
const auto& layoutSynthesisEnd = std::chrono::system_clock::now();
NAComputation code =
SELF.generate(singleQubitGateLayers, placement, routing);
const auto& codeGenerationEnd = std::chrono::system_clock::now();
assert(code.validate().first);

statistics_.schedulingTime =
std::chrono::duration_cast<std::chrono::microseconds>(schedulingEnd -
schedulingStart)
Expand Down Expand Up @@ -203,25 +194,44 @@ class Compiler : protected Scheduler,
avg, max);
}
#endif // SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_DEBUG

SPDLOG_DEBUG("Analyzing reuse...");
const auto reuseAnalysisStart = std::chrono::system_clock::now();
const auto& reuseQubits = SELF.analyzeReuse(twoQubitGateLayers);
const auto reuseAnalysisEnd = std::chrono::system_clock::now();
statistics_.reuseAnalysisTime =
std::chrono::duration_cast<std::chrono::microseconds>(reuseAnalysisEnd -
schedulingEnd)
std::chrono::duration_cast<std::chrono::microseconds>(
reuseAnalysisEnd - reuseAnalysisStart)
.count();
SPDLOG_INFO("Time for reuse analysis: {}us", statistics_.reuseAnalysisTime);

SPDLOG_DEBUG("Synthesizing layout...");
const auto layoutSynthesisStart = std::chrono::system_clock::now();
const auto& [placement, routing] = LayoutSynthesizer::synthesize(
qComp.getNqubits(), twoQubitGateLayers, reuseQubits);
const auto layoutSynthesisEnd = std::chrono::system_clock::now();
statistics_.layoutSynthesisTime =
std::chrono::duration_cast<std::chrono::microseconds>(
layoutSynthesisEnd - reuseAnalysisEnd)
layoutSynthesisEnd - layoutSynthesisStart)
.count();
statistics_.layoutSynthesizerStatistics =
SELF.getLayoutSynthesisStatistics();
SPDLOG_INFO("Time for layout synthesis: {}us",
statistics_.layoutSynthesisTime);

SPDLOG_DEBUG("Generating code...");
const auto codeGenerationStart = std::chrono::system_clock::now();
NAComputation code =
SELF.generate(singleQubitGateLayers, placement, routing);
const auto codeGenerationEnd = std::chrono::system_clock::now();
assert(code.validate().first);
statistics_.codeGenerationTime =
std::chrono::duration_cast<std::chrono::microseconds>(
codeGenerationEnd - layoutSynthesisEnd)
codeGenerationEnd - codeGenerationStart)
.count();
SPDLOG_INFO("Time for code generation: {}us",
statistics_.codeGenerationTime);

statistics_.totalTime =
std::chrono::duration_cast<std::chrono::microseconds>(
codeGenerationEnd - schedulingStart)
Expand Down Expand Up @@ -254,7 +264,7 @@ class RoutingAgnosticCompiler final
RoutingAgnosticCompiler(const Architecture& architecture,
const Config& config)
: Compiler(architecture, config) {}
RoutingAgnosticCompiler(const Architecture& architecture)
explicit RoutingAgnosticCompiler(const Architecture& architecture)
: Compiler(architecture) {}
};

Expand All @@ -275,7 +285,7 @@ class RoutingAwareCompiler final
public:
RoutingAwareCompiler(const Architecture& architecture, const Config& config)
: Compiler(architecture, config) {}
RoutingAwareCompiler(const Architecture& architecture)
explicit RoutingAwareCompiler(const Architecture& architecture)
: Compiler(architecture) {}
};
} // namespace na::zoned
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,11 @@ class PlaceAndRouteSynthesizer : public LayoutSynthesizerBase,
: PlaceAndRouteSynthesizer(architecture, Config{}) {}

public:
[[nodiscard]] auto synthesize(
size_t nQubits, const std::vector<TwoQubitGateLayer>& twoQubitGateLayers,
const std::vector<std::unordered_set<qc::Qubit>>& reuseQubits) -> Layout {
[[nodiscard]] auto
synthesize(size_t nQubits,
const std::vector<TwoQubitGateLayer>& twoQubitGateLayers,
const std::vector<std::unordered_set<qc::Qubit>>& reuseQubits)
-> Layout override {
const auto& placementStart = std::chrono::system_clock::now();
const auto& placement =
SELF.place(nQubits, twoQubitGateLayers, reuseQubits);
Expand Down
2 changes: 1 addition & 1 deletion include/na/zoned/layout_synthesizer/placer/AStarPlacer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ class AStarPlacer : public PlacerBase {
place(size_t nQubits,
const std::vector<TwoQubitGateLayer>& twoQubitGateLayers,
const std::vector<std::unordered_set<qc::Qubit>>& reuseQubits)
-> std::vector<Placement>;
-> std::vector<Placement> override;

private:
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ class VertexMatchingPlacer : public PlacerBase {
place(size_t nQubits,
const std::vector<TwoQubitGateLayer>& twoQubitGateLayers,
const std::vector<std::unordered_set<qc::Qubit>>& reuseQubits)
-> std::vector<Placement>;
-> std::vector<Placement> override;

private:
/// Generate qubit initial layout
Expand Down
Loading
Loading