-
-
Notifications
You must be signed in to change notification settings - Fork 32
♻️ Replace pybind11 with nanobind
#911
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
Conversation
📝 WalkthroughSummary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings. WalkthroughMigrate Python bindings from pybind11 to nanobind across many modules, update CI/build (pyproject, CMake, GitHub Actions), remove pybind11_json, bump MQT Core to 3.4.0, and add Stable ABI / CPython 3.12 wheel packaging and changelog entries. Changes
Sequence Diagram(s)(omitted — changes are primarily API/binding and build migrations, not new multi-component runtime control flow) Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 📜 Recent review detailsConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro 📒 Files selected for processing (1)
🧰 Additional context used🧠 Learnings (3)📓 Common learnings📚 Learning: 2026-01-09T17:58:10.350ZApplied to files:
📚 Learning: 2025-10-14T14:37:38.047ZApplied to files:
🪛 LanguageToolCHANGELOG.md[typographical] ~19-~19: To join two clauses or introduce examples, consider using an em dash. (DASH_RULE) ⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (13)
🔇 Additional comments (1)
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. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In @bindings/clifford_synthesis/clifford_synthesis.cpp:
- Around line 197-200: The call to synthesizer.def using
nb::init<qc::QuantumComputation&, bool>() is missing a comma between the
argument specifier "use_destabilizers"_a and the following docstring which
causes a compilation error; fix by inserting a comma after "use_destabilizers"_a
so the parameter list and the docstring are separate arguments in the
synthesizer.def invocation.
In @bindings/hybrid_mapper/hybrid_mapper.cpp:
- Around line 43-47: The enum registration for nb::enum_<na::InitialMapping> is
missing a comma between the enum name and its docstring, causing adjacent string
literal concatenation; update the call that starts
nb::enum_<na::InitialMapping>(m, "InitialCircuitMapping" "Initial mapping
between circuit qubits and hardware qubits.") to include the missing comma so
the enum name is "InitialCircuitMapping" and the docstring is passed separately
(i.e., separate the two string literals in the nb::enum_ call that uses m and
"InitialCircuitMapping").
In @bindings/sc/sc.cpp:
- Line 83: Update the module docstring set via m.doc() to replace the outdated
"pybind11" reference with "nanobind" (e.g., change the string in m.doc() to
mention nanobind and the MQT QMAP quantum circuit mapping tool) so the binding
description accurately reflects the current binding library.
📜 Review details
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
uv.lockis excluded by!**/*.lock
📒 Files selected for processing (17)
.github/workflows/ci.yml.pre-commit-config.yamlCHANGELOG.mdCMakeLists.txtUPGRADING.mdbindings/clifford_synthesis/CMakeLists.txtbindings/clifford_synthesis/clifford_synthesis.cppbindings/hybrid_mapper/CMakeLists.txtbindings/hybrid_mapper/hybrid_mapper.cppbindings/na/nasp/CMakeLists.txtbindings/na/nasp/nasp.cppbindings/na/zoned/CMakeLists.txtbindings/na/zoned/zoned.cppbindings/sc/CMakeLists.txtbindings/sc/sc.cppcmake/ExternalDependencies.cmakepyproject.toml
🧰 Additional context used
🧠 Learnings (29)
📓 Common learnings
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1383
File: bindings/dd/register_matrix_dds.cpp:64-109
Timestamp: 2025-12-15T01:54:22.129Z
Learning: In the munich-quantum-toolkit/core repository, after migrating to nanobind, docstrings for Python bindings are now added directly in the C++ binding code (using R"pb(...)pb" syntax) and stub files (.pyi) are auto-generated using the `bindings/generate-stubs.sh` script. This replaces the previous pybind11 approach where docstrings were manually maintained in stub files.
Learnt from: burgholzer
Repo: munich-quantum-toolkit/qcec PR: 817
File: pyproject.toml:81-82
Timestamp: 2026-01-09T17:58:10.350Z
Learning: In the Munich Quantum Toolkit projects using nanobind, setting `wheel.py-api = "cp312"` in `[tool.scikit-build]` enables Stable ABI wheels only for Python 3.12+ (where nanobind supports it), while automatically building regular non-ABI3 wheels for earlier Python versions (3.10, 3.11) and free-threading builds (3.14t). This allows a single configuration to appropriately handle both old and new Python versions without forcing incompatible ABI requirements.
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1383
File: bindings/ir/register_permutation.cpp:153-171
Timestamp: 2025-12-22T01:25:21.609Z
Learning: In the munich-quantum-toolkit/core repository, when using nanobind iterator factory functions like `make_key_iterator` and `make_iterator`, the unqualified form (without explicit `nb::` prefix) is preferred. The clang-tidy configuration suggests removal of explicit namespace qualification, relying on ADL (Argument-Dependent Lookup) to resolve these functions correctly.
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1355
File: bindings/fomac/fomac.cpp:227-264
Timestamp: 2025-12-07T01:21:27.544Z
Learning: In the munich-quantum-toolkit/core repository, docstrings for Python bindings are added to the corresponding stub files (.pyi) rather than directly in the pybind11 C++ bindings code. This practice may change if the project adopts nanobind with automatic stub generation.
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1383
File: bindings/fomac/fomac.cpp:111-116
Timestamp: 2025-12-19T00:05:54.428Z
Learning: In the munich-quantum-toolkit/core repository after migrating to nanobind, lifetime management differs from pybind11: `nb::keep_alive<nurse, patient>()` does not exist in nanobind. Instead, use `nb::rv_policy::reference_internal` when binding methods that return objects referencing internal state of the parent object (e.g., Session::getDevices returning Device objects that depend on the Session). This tells nanobind to keep the parent alive while children exist.
📚 Learning: 2026-01-09T17:58:10.350Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/qcec PR: 817
File: pyproject.toml:81-82
Timestamp: 2026-01-09T17:58:10.350Z
Learning: In the Munich Quantum Toolkit projects using nanobind, setting `wheel.py-api = "cp312"` in `[tool.scikit-build]` enables Stable ABI wheels only for Python 3.12+ (where nanobind supports it), while automatically building regular non-ABI3 wheels for earlier Python versions (3.10, 3.11) and free-threading builds (3.14t). This allows a single configuration to appropriately handle both old and new Python versions without forcing incompatible ABI requirements.
Applied to files:
UPGRADING.mdbindings/sc/CMakeLists.txt.github/workflows/ci.ymlpyproject.tomlCHANGELOG.mdcmake/ExternalDependencies.cmake
📚 Learning: 2025-10-09T22:15:59.924Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1246
File: pyproject.toml:340-341
Timestamp: 2025-10-09T22:15:59.924Z
Learning: Qiskit publishes ABI3 wheels (e.g., cp39-abi3) that are forward-compatible with newer Python versions including Python 3.14, so no explicit Python 3.14 wheels are required for qiskit to work on Python 3.14.
Applied to files:
UPGRADING.mdpyproject.toml
📚 Learning: 2025-12-15T01:54:22.129Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1383
File: bindings/dd/register_matrix_dds.cpp:64-109
Timestamp: 2025-12-15T01:54:22.129Z
Learning: In the munich-quantum-toolkit/core repository, after migrating to nanobind, docstrings for Python bindings are now added directly in the C++ binding code (using R"pb(...)pb" syntax) and stub files (.pyi) are auto-generated using the `bindings/generate-stubs.sh` script. This replaces the previous pybind11 approach where docstrings were manually maintained in stub files.
Applied to files:
UPGRADING.mdbindings/sc/CMakeLists.txt.github/workflows/ci.ymlbindings/na/nasp/CMakeLists.txtbindings/hybrid_mapper/CMakeLists.txtbindings/na/zoned/CMakeLists.txtbindings/clifford_synthesis/CMakeLists.txtpyproject.tomlcmake/ExternalDependencies.cmakebindings/na/nasp/nasp.cppbindings/hybrid_mapper/hybrid_mapper.cppbindings/sc/sc.cppbindings/clifford_synthesis/clifford_synthesis.cppbindings/na/zoned/zoned.cpp
📚 Learning: 2025-10-11T19:39:32.050Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/debugger PR: 160
File: pyproject.toml:54-54
Timestamp: 2025-10-11T19:39:32.050Z
Learning: Qiskit packages use cp39-abi3 wheels (stable ABI) which are forward-compatible with Python 3.9+ including Python 3.14, even if the package classifiers don't explicitly list Python 3.14 support.
Applied to files:
UPGRADING.mdpyproject.toml
📚 Learning: 2025-12-21T22:35:08.572Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1383
File: bindings/fomac/fomac.cpp:348-364
Timestamp: 2025-12-21T22:35:08.572Z
Learning: In the munich-quantum-toolkit/core repository's nanobind bindings, use `.sig("...")` on parameter arguments that have vector or container defaults (e.g., `"sites"_a.sig("...") = std::vector<fomac::Session::Device::Site>{}`) to prevent exposing mutable defaults in the Python API, which would be flagged as a code smell by Python linters. This pattern is preferred over removing `.sig("...")` even though it shows `...` in the stub signature.
Applied to files:
bindings/sc/CMakeLists.txtbindings/na/nasp/CMakeLists.txtbindings/hybrid_mapper/CMakeLists.txtbindings/na/zoned/CMakeLists.txtbindings/clifford_synthesis/CMakeLists.txtbindings/sc/sc.cpp
📚 Learning: 2025-12-07T01:21:27.544Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1355
File: bindings/fomac/fomac.cpp:227-264
Timestamp: 2025-12-07T01:21:27.544Z
Learning: In the munich-quantum-toolkit/core repository, docstrings for Python bindings are added to the corresponding stub files (.pyi) rather than directly in the pybind11 C++ bindings code. This practice may change if the project adopts nanobind with automatic stub generation.
Applied to files:
bindings/sc/CMakeLists.txtbindings/na/nasp/CMakeLists.txtbindings/hybrid_mapper/CMakeLists.txtbindings/na/zoned/CMakeLists.txtbindings/clifford_synthesis/CMakeLists.txtpyproject.tomlbindings/na/nasp/nasp.cppbindings/hybrid_mapper/hybrid_mapper.cppbindings/sc/sc.cppbindings/clifford_synthesis/clifford_synthesis.cpp
📚 Learning: 2025-12-28T17:14:53.890Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1403
File: src/qdmi/na/CMakeLists.txt:31-38
Timestamp: 2025-12-28T17:14:53.890Z
Learning: In the munich-quantum-toolkit/core repository, the NA device generator target (mqt-core-qdmi-na-device-gen) is intentionally propagated to MQT_CORE_TARGETS via list(APPEND) because it's publicly linked to the NA device library (the NA device uses a public function from the generator). The SC device generator is not propagated because it has no such dependency with the SC device library.
Applied to files:
bindings/sc/CMakeLists.txtbindings/na/nasp/CMakeLists.txtbindings/hybrid_mapper/CMakeLists.txtbindings/na/zoned/CMakeLists.txtbindings/clifford_synthesis/CMakeLists.txtcmake/ExternalDependencies.cmakebindings/na/nasp/nasp.cpp
📚 Learning: 2025-12-22T01:25:21.609Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1383
File: bindings/ir/register_permutation.cpp:153-171
Timestamp: 2025-12-22T01:25:21.609Z
Learning: In the munich-quantum-toolkit/core repository, when using nanobind iterator factory functions like `make_key_iterator` and `make_iterator`, the unqualified form (without explicit `nb::` prefix) is preferred. The clang-tidy configuration suggests removal of explicit namespace qualification, relying on ADL (Argument-Dependent Lookup) to resolve these functions correctly.
Applied to files:
bindings/sc/CMakeLists.txtbindings/na/nasp/CMakeLists.txtbindings/hybrid_mapper/CMakeLists.txtbindings/na/zoned/CMakeLists.txtbindings/clifford_synthesis/CMakeLists.txtbindings/na/nasp/nasp.cppbindings/hybrid_mapper/hybrid_mapper.cppbindings/sc/sc.cppbindings/clifford_synthesis/clifford_synthesis.cppbindings/na/zoned/zoned.cpp
📚 Learning: 2025-12-19T00:05:54.428Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1383
File: bindings/fomac/fomac.cpp:111-116
Timestamp: 2025-12-19T00:05:54.428Z
Learning: In the munich-quantum-toolkit/core repository after migrating to nanobind, lifetime management differs from pybind11: `nb::keep_alive<nurse, patient>()` does not exist in nanobind. Instead, use `nb::rv_policy::reference_internal` when binding methods that return objects referencing internal state of the parent object (e.g., Session::getDevices returning Device objects that depend on the Session). This tells nanobind to keep the parent alive while children exist.
Applied to files:
bindings/sc/CMakeLists.txtbindings/na/nasp/CMakeLists.txtbindings/hybrid_mapper/CMakeLists.txtbindings/na/zoned/CMakeLists.txtbindings/na/nasp/nasp.cppbindings/hybrid_mapper/hybrid_mapper.cppbindings/sc/sc.cppbindings/clifford_synthesis/clifford_synthesis.cppbindings/na/zoned/zoned.cpp
📚 Learning: 2025-10-10T08:09:54.528Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1246
File: bindings/CMakeLists.txt:0-0
Timestamp: 2025-10-10T08:09:54.528Z
Learning: In the Munich Quantum Toolkit (MQT) Core project, scikit-build-core is configured with `wheel.install-dir = "mqt/core"` in pyproject.toml, which automatically prefixes all CMake `DESTINATION` paths with `mqt/core/` during wheel installation. Therefore, CMake install destinations are relative to the `mqt/core` package namespace, not `site-packages`.
Applied to files:
bindings/sc/CMakeLists.txt.github/workflows/ci.ymlbindings/na/nasp/CMakeLists.txtbindings/hybrid_mapper/CMakeLists.txtbindings/na/zoned/CMakeLists.txtbindings/clifford_synthesis/CMakeLists.txtpyproject.tomlcmake/ExternalDependencies.cmake
📚 Learning: 2025-10-10T08:10:16.394Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1246
File: test/python/na/test_na_fomac.py:35-0
Timestamp: 2025-10-10T08:10:16.394Z
Learning: In the munich-quantum-toolkit/core repository, scikit-build-core is configured with `wheel.install-dir = "mqt/core"` in pyproject.toml, which means CMake `install()` commands with `DESTINATION <path>` install files relative to `mqt/core/` in the wheel, making them accessible via `files("mqt.core").joinpath("<path>")`.
Applied to files:
bindings/sc/CMakeLists.txtbindings/hybrid_mapper/CMakeLists.txtbindings/clifford_synthesis/CMakeLists.txtpyproject.tomlcmake/ExternalDependencies.cmake
📚 Learning: 2025-12-15T01:59:17.023Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1383
File: python/mqt/core/ir/operations.pyi:9-16
Timestamp: 2025-12-15T01:59:17.023Z
Learning: In the munich-quantum-toolkit/core repository, stub files (.pyi) are auto-generated by nanobind's stubgen tool and should not be manually modified for style preferences, as changes would be overwritten during regeneration.
Applied to files:
bindings/sc/CMakeLists.txtbindings/na/nasp/CMakeLists.txtbindings/hybrid_mapper/CMakeLists.txtbindings/clifford_synthesis/CMakeLists.txtbindings/hybrid_mapper/hybrid_mapper.cpp
📚 Learning: 2026-01-04T23:54:33.540Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1356
File: src/qdmi/na/CMakeLists.txt:179-184
Timestamp: 2026-01-04T23:54:33.540Z
Learning: In the munich-quantum-toolkit/core repository, MSVC link-time code generation (LTCG) must be disabled for the NA device dynamic library target (mqt-core-qdmi-na-device-dyn) on Windows to avoid link errors and missing symbols. This issue affects both release-only builds and debug/release mixed builds, not just debug/release mixing scenarios.
Applied to files:
bindings/sc/CMakeLists.txtbindings/na/nasp/CMakeLists.txtbindings/na/zoned/CMakeLists.txt
📚 Learning: 2025-12-28T17:13:36.900Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1403
File: pyproject.toml:98-102
Timestamp: 2025-12-28T17:13:36.900Z
Learning: In the munich-quantum-toolkit/core project, scikit-build-core is intelligent enough to skip build targets listed in pyproject.toml that don't exist for a given platform, so platform-specific targets (like `-dyn` targets conditioned on `NOT WIN32`) can be unconditionally listed in `build.targets` without causing Windows build failures.
Applied to files:
bindings/sc/CMakeLists.txtpyproject.toml
📚 Learning: 2025-12-13T20:08:45.549Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/qmap PR: 862
File: pyproject.toml:65-66
Timestamp: 2025-12-13T20:08:45.549Z
Learning: In the qmap project (pyproject.toml), maintain broad compatibility with dependencies across supported Python versions. Avoid artificially raising minimum version requirements unless there's a specific need (e.g., to guarantee binary wheel availability for certain Python versions, or to access required features). The goal is to keep the software as broadly compatible as possible with the rest of the ecosystem.
Applied to files:
.github/workflows/ci.yml
📚 Learning: 2025-11-04T15:22:19.558Z
Learnt from: marcelwa
Repo: munich-quantum-toolkit/core PR: 1243
File: test/python/qdmi/qiskit/conftest.py:155-157
Timestamp: 2025-11-04T15:22:19.558Z
Learning: The munich-quantum-toolkit/core repository requires Python 3.10 or later, so Python 3.10+ features (such as `zip(..., strict=...)`, pattern matching, etc.) are acceptable and should not be flagged as compatibility issues.
Applied to files:
.github/workflows/ci.ymlpyproject.toml
📚 Learning: 2025-10-09T13:14:10.178Z
Learnt from: DRovara
Repo: munich-quantum-toolkit/core PR: 1108
File: mlir/lib/Dialect/MQTOpt/Transforms/ReplaceBasisStateControlsWithIfPattern.cpp:219-221
Timestamp: 2025-10-09T13:14:10.178Z
Learning: The MQT Core project (munich-quantum-toolkit/core repository) uses the C++20 standard, not C++17. C++20 features such as abbreviated function templates (e.g., `const auto&` parameters) are supported and valid in this codebase.
Applied to files:
.github/workflows/ci.ymlbindings/na/nasp/CMakeLists.txtbindings/na/zoned/CMakeLists.txtcmake/ExternalDependencies.cmakebindings/na/nasp/nasp.cpp
📚 Learning: 2026-01-09T00:27:20.419Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core-plugins-catalyst PR: 39
File: .pre-commit-config.yaml:135-135
Timestamp: 2026-01-09T00:27:20.419Z
Learning: In the munich-quantum-toolkit/core-plugins-catalyst repository, `.pre-commit-config.yaml` intentionally uses `https://github.com/adhtruong/mirrors-typos` instead of the official `https://github.com/crate-ci/typos` repository to avoid pre-commit autoupdate tag confusion described in https://github.com/crate-ci/typos/issues/390.
Applied to files:
.pre-commit-config.yaml
📚 Learning: 2025-12-13T20:08:32.333Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/qmap PR: 862
File: pyproject.toml:65-66
Timestamp: 2025-12-13T20:08:32.333Z
Learning: In pyproject.toml, maintain broad compatibility by avoiding unnecessary increases to the minimum Python version. Only raise minimum version when there is a concrete need (e.g., to guarantee binary wheel availability or access to required features). This helps keep the project compatible with the ecosystem and other dependencies across supported Python versions.
Applied to files:
pyproject.toml
📚 Learning: 2025-12-14T16:51:52.504Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core-plugins-catalyst PR: 23
File: .readthedocs.yaml:13-18
Timestamp: 2025-12-14T16:51:52.504Z
Learning: In the munich-quantum-toolkit/core-plugins-catalyst repository, LLVM and MLIR toolchains are required for the documentation build because `uv run` includes a full build of the package, which compiles C++/MLIR extensions using scikit-build-core.
Applied to files:
pyproject.toml
📚 Learning: 2025-10-14T14:37:38.047Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/yaqs PR: 212
File: CHANGELOG.md:12-15
Timestamp: 2025-10-14T14:37:38.047Z
Learning: In the munich-quantum-toolkit/yaqs project, changelog entries follow the template: "- $TITLE ([#$NUMBER]($URL)) ([**AUTHOR**](https://github.com/$AUTHOR))". Issue references should not be included in changelog entries; the PR number is sufficient for traceability.
Applied to files:
CHANGELOG.md
📚 Learning: 2025-12-05T17:45:37.602Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1360
File: .github/workflows/reusable-mlir-tests.yml:40-43
Timestamp: 2025-12-05T17:45:37.602Z
Learning: In the munich-quantum-toolkit/core repository, patch releases of LLVM dependencies don't require documentation updates, changelog entries, or additional tests beyond what's validated by passing CI checks.
Applied to files:
cmake/ExternalDependencies.cmake
📚 Learning: 2025-12-05T15:57:39.701Z
Learnt from: flowerthrower
Repo: munich-quantum-toolkit/core-plugins-catalyst PR: 3
File: lib/Conversion/CatalystQuantumToMQTOpt/CMakeLists.txt:22-25
Timestamp: 2025-12-05T15:57:39.701Z
Learning: The munich-quantum-toolkit projects (core and core-plugins-catalyst) use `file(GLOB_RECURSE ...)` patterns in CMakeLists.txt files to collect header files, following an established convention in the parent repository for consistency across the codebase.
Applied to files:
cmake/ExternalDependencies.cmake
📚 Learning: 2025-11-03T23:09:26.881Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1287
File: test/qdmi/dd/CMakeLists.txt:9-21
Timestamp: 2025-11-03T23:09:26.881Z
Learning: The CMake functions `generate_device_defs_executable` and `generate_prefixed_qdmi_headers` used in QDMI device test CMakeLists.txt files are provided by the external QDMI library (fetched via FetchContent from https://github.com/Munich-Quantum-Software-Stack/qdmi.git), specifically in the cmake/PrefixHandling.cmake module of the QDMI repository.
Applied to files:
cmake/ExternalDependencies.cmake
📚 Learning: 2025-11-20T18:19:31.857Z
Learnt from: lsschmid
Repo: munich-quantum-toolkit/qmap PR: 832
File: src/hybridmap/HybridNeutralAtomMapper.cpp:1679-1715
Timestamp: 2025-11-20T18:19:31.857Z
Learning: In src/hybridmap/HybridNeutralAtomMapper.cpp, the compareSwapAndBridge and compareShuttlingAndFlyingAncilla methods intentionally use division by zero to produce infinity when distance reductions are zero or negative. This infinity value marks that option as highly unfavorable in cost comparisons, which is the intended behavior rather than a bug.
Applied to files:
bindings/hybrid_mapper/hybrid_mapper.cpp
📚 Learning: 2025-11-27T08:52:06.428Z
Learnt from: lsschmid
Repo: munich-quantum-toolkit/qmap PR: 832
File: src/hybridmap/HybridNeutralAtomMapper.cpp:1379-1383
Timestamp: 2025-11-27T08:52:06.428Z
Learning: In src/hybridmap/HybridNeutralAtomMapper.cpp, the getBestMovePos function throws std::runtime_error when no move position is found (finalBestPos.coords is empty). This behavior is acceptable for current use cases since tight architectures are not a concern. A future improvement would be to fall back to SWAP-based strategies instead of throwing.
Applied to files:
bindings/hybrid_mapper/hybrid_mapper.cpp
📚 Learning: 2025-11-05T09:23:46.540Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1287
File: src/qdmi/dd/Device.cpp:492-521
Timestamp: 2025-11-05T09:23:46.540Z
Learning: In the munich-quantum-toolkit/core repository, the `qasm3::Importer::imports()` function is backwards compatible with OpenQASM 2 programs. Therefore, it can be used to parse both QASM2 and QASM3 program formats without requiring separate importers for each version.
Applied to files:
bindings/clifford_synthesis/clifford_synthesis.cpp
📚 Learning: 2025-12-04T06:59:40.314Z
Learnt from: MatthiasReumann
Repo: munich-quantum-toolkit/core PR: 1301
File: mlir/lib/Dialect/MQTOpt/Transforms/Transpilation/LayeredUnit.cpp:84-85
Timestamp: 2025-12-04T06:59:40.314Z
Learning: In the MQTOpt MLIR routing passes (NaiveRoutingPassSC, AStarRoutingPassSC), the input IR is guaranteed to contain only 1-qubit and 2-qubit gates. All 3+-qubit gates must be decomposed before routing; otherwise the input IR is invalid. This invariant allows skipTwoQubitBlock in LayeredUnit.cpp to safely assert wires.size() == 2.
Applied to files:
bindings/na/zoned/zoned.cpp
🔇 Additional comments (36)
.github/workflows/ci.yml (1)
158-158: LGTM!The nanobind version (
2.10.2) correctly matches the version specified inpyproject.tomlbuild-system requirements, ensuring consistency between CI linting and the actual build.UPGRADING.md (2)
7-17: LGTM!The documentation clearly explains the Stable ABI wheel migration and accurately reflects the wheel matrix. Based on learnings, the
cp312Stable ABI configuration in nanobind correctly handles Python 3.10/3.11 with regular wheels while providing Stable ABI wheels for 3.12+.
41-41: LGTM!The wording change from "CI" to "CI/CD" is appropriate as it reflects that both continuous integration and deployment pipelines benefit from reduced build times.
CHANGELOG.md (2)
186-186: PR link added correctly.The PR link format follows the established convention in the changelog.
14-17: Verify the PR number references in the changelog entries.The changelog references
[#909]but I cannot locate this PR in the public repository to verify if it's the correct reference for the nanobind migration and Stable ABI wheel changes. Please confirm that #909 is the intended PR number and ensure the changelog accurately reflects the PR that introduced these changes..pre-commit-config.yaml (1)
137-137: LGTM!The capitalization check correctly updated to catch improper capitalization of
Nanobind(should be lowercasenanobind), reflecting the library naming convention after the migration.pyproject.toml (5)
11-14: LGTM!The build-system requires correctly updated to use
nanobind>=2.10.2andmqt.core~=3.4.0, maintaining version consistency with runtime dependencies.
86-87: LGTM!The
wheel.py-api = "cp312"configuration correctly enables Stable ABI wheels for Python 3.12+ while automatically building regular non-ABI3 wheels for earlier Python versions (3.10, 3.11) and free-threading builds (3.14t). Based on learnings from the Munich Quantum Toolkit projects, this is the expected configuration for nanobind-based Stable ABI support.
350-354: LGTM!The auditwheel exclusions correctly updated to reference the new
3.4version suffix for mqt-core shared libraries, aligning with themqt.core~=3.4.0dependency.
424-424: LGTM!The test dependency
mqt.qcec>=3.4.0correctly updated to align with the mqt.core version bump.
370-373: The selectorcp312-*correctly covers all Stable ABI wheels. Whenwheel.py-api = "cp312"is set, a single Stable ABI wheel taggedcp312-abi3is produced and is forward-compatible with Python 3.12+; separate wheels taggedcp313-abi3orcp314-abi3are not created. Thecp312-*selector matches this wheel appropriately.Likely an incorrect or invalid review comment.
bindings/na/nasp/nasp.cpp (2)
19-31: LGTM: Nanobind migration setup is correct.The namespace alias, module declaration, and
mqt.core.irimport follow the established nanobind migration pattern used across the MQT ecosystem.
34-50: LGTM: Class bindings and JSON exposure are correctly migrated.The
NASolverandNASolver::Resultbindings correctly use nanobind conventions:
nb::init<>()for constructorsnb::none()for optional parameter defaults- JSON conversion via Python's
json.loadsis the expected pattern when migrating from pybind11_jsonbindings/na/zoned/zoned.cpp (3)
76-97: LGTM: Nanobind constructor binding with placement new and keep_alive.The
__init__binding using placement new (new (self) ...) combined withnb::keep_alive<1, 2>()is the correct nanobind pattern for custom constructor logic where the compiler object needs to outlive the architecture reference. This properly mirrors the pybind11 keep_alive semantics for constructor bindings.
130-136: LGTM: JSON statistics exposure is correct.The
stats()method correctly imports Python'sjsonmodule and usesjson.loadsto convert the dumped nlohmann::json to a Python object, which is the standard pattern after removing pybind11_json dependency.
145-182: LGTM: RoutingAwareCompiler binding follows the same correct pattern.The constructor binding with placement new and
nb::keep_alive<1, 2>()is consistent with the RoutingAgnosticCompiler binding.bindings/hybrid_mapper/hybrid_mapper.cpp (3)
49-88: LGTM: MapperParameters binding with def_rw is correct.The
def_rwbindings correctly expose read-write properties in nanobind, which is the equivalent of pybind11'sdef_readwrite.
103-135: LGTM: NeutralAtomArchitecture binding correctly uses def_rw and def_prop_ro.The mix of
def_rwfor writable attributes anddef_prop_rofor read-only getter-based properties follows nanobind conventions correctly.
153-164: LGTM: NeutralAtomMapper lifetime management is correct.Using
nb::keep_alive<1, 2>()andnb::keep_alive<1, 3>()ensures that botharchandparamsoutlive the mapper instance, which is the correct approach for constructor arguments that are stored by reference.bindings/sc/sc.cpp (3)
86-174: LGTM: Enum bindings correctly migrated to nanobind.All enum bindings use
nb::enum_<>with proper value definitions. The removal ofexport_values()is consistent with nanobind's default behavior of scoped enums.
324-435: LGTM: Architecture and Properties bindings correctly use nanobind patterns.The
def_prop_rwfor getter/setter pairs andnb::overload_cast<>for overloaded methods are correctly applied.
218-223: JSON conversion pattern differs from other files.This file uses
json.dumps(config.json())which is inconsistent with the pattern in other migrated files (e.g.,nasp.cpp,zoned.cpp) that usejson.loads(result.json().dump()).If
config.json()returns anlohmann::jsonobject, nanobind won't automatically convert it to a Python dict without pybind11_json, anddumpsexpects a Python object, not a C++ object.bindings/na/zoned/CMakeLists.txt (1)
9-19: LGTM: CMake binding configuration correctly migrated.The change from
add_mqt_python_bindingtoadd_mqt_python_binding_nanobindand removal ofpybind11_jsonfrom linked libraries is consistent with the nanobind migration.bindings/na/nasp/CMakeLists.txt (1)
9-19: LGTM: CMake binding configuration correctly migrated.Consistent with the other binding modules, the helper function is updated to the nanobind variant and pybind11_json is removed.
CMakeLists.txt (1)
62-63: LGTM: Stable ABI component configuration is correct.Using
${SKBUILD_SABI_COMPONENT}variable (set by scikit-build-core) allows conditional inclusion ofDevelopment.SABIModuleonly when building Stable ABI wheels. Based on learnings, this works withwheel.py-api = "cp312"in pyproject.toml to enable Stable ABI wheels for Python 3.12+ while building regular wheels for earlier versions.bindings/clifford_synthesis/CMakeLists.txt (1)
9-19: LGTM!The migration to
add_mqt_python_binding_nanobindis correctly implemented. The removal ofpybind11_jsonfromLINK_LIBSis appropriate since nanobind uses a different JSON handling approach (as seen in the corresponding.cppfile usingjson.dumpsvia Python import).bindings/sc/CMakeLists.txt (1)
9-22: LGTM!The migration to nanobind is correctly applied. The
Z3_FOUNDcompile definition is preserved, and the removal ofpybind11_jsonfrom link libraries aligns with the nanobind JSON handling pattern.bindings/hybrid_mapper/CMakeLists.txt (1)
9-19: LGTM!The migration follows the consistent pattern across all binding modules—switching to
add_mqt_python_binding_nanobindand removingpybind11_jsondependency.cmake/ExternalDependencies.cmake (2)
36-40: LGTM!The nanobind detection pattern correctly mirrors the mqt-core detection approach: obtaining the CMake directory via the Python module and then using
find_package. Thenanobind_ROOTvariable is implicitly used by CMake'sfind_packageto locate the package configuration.
44-48: Verify MQT Core 3.4.0 availability.The version bump to 3.4.0 is available with Git tag v3.4.0. Ensure the referenced commit
6bcc01e7d135058c6439c64fdd5f14b65ab88816is incorporated into your dependency resolution.Likely an incorrect or invalid review comment.
bindings/clifford_synthesis/clifford_synthesis.cpp (6)
20-32: LGTM!The header migration from pybind11 to nanobind is correct. The
nbnamespace alias and use ofnb::literalsfor argument syntax follow nanobind conventions. The explicit import ofmqt.core.irensures the dependent types are registered before use.
35-49: LGTM!The enum bindings are correctly migrated to
nb::enum_. The docstrings are preserved inline, which aligns with the nanobind approach where docstrings are added directly in C++ code and stub files are auto-generated.
52-142: LGTM!The
SynthesisConfigurationbindings correctly use:
nb::init<>()for the constructordef_rwfor read-write member bindings (nanobind equivalent of pybind11'sdef_readwrite)- JSON exposure via Python's
json.dumpsmodule, which is the correct nanobind pattern for handling nlohmann::jsonBased on learnings from the mqt-core migration.
145-170: LGTM!The
SynthesisResultsbindings correctly usedef_prop_ro(nanobind equivalent of pybind11'sdef_property_readonly) for read-only property bindings.
172-185: LGTM!The
Tableauclass bindings correctly usenb::init<>constructors with the nanobind argument syntax.
209-213: LGTM!The
def_prop_robindings forresultsandresult_circuitare correctly implemented. The lambda forresult_circuitproperly imports QASM using theqasm3::Importer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🤖 Fix all issues with AI agents
In @bindings/clifford_synthesis/clifford_synthesis.cpp:
- Around line 210-214: The binding for the read-only "results" property exposes
an internal Results& via cs::CliffordSynthesizer::getResults but lacks a
lifetime policy; update the synthesizer.def_prop_ro("results",
&cs::CliffordSynthesizer::getResults, ...) call to include
nb::rv_policy::reference_internal so the Python Results object is tied to the
parent CliffordSynthesizer; leave the existing result_circuit lambda (which
calls self.getResults().getResultCircuit()) unchanged.
In @bindings/na/nasp/nasp.cpp:
- Around line 44-50: Add a nanobind docstring to the binding for
NAStatePreparationSolver.Result by supplying an R"pb(... )pb" docstring to the
nb::class_<na::NASolver::Result>(m, "NAStatePreparationSolver.Result") and/or to
the .def("json", ...) call so the generated stub includes the method/class
documentation; update the .def("json", [](const na::NASolver::Result& result) {
... }) invocation to pass the docstring as the final argument (using the
R"pb(...)pb" literal) describing what json() returns and its behavior.
In @bindings/sc/sc.cpp:
- Around line 428-433: The property bindings for Architecture.coupling_map and
Architecture.properties use def_prop_rw with getters that return references
(Architecture::getCouplingMap and Architecture::getProperties); update those
def_prop_rw calls to pass nb::rv_policy::reference_internal as the fourth
argument so nanobind keeps the parent Architecture alive while the returned
CouplingMap&/Properties& are used.
- Around line 216-221: The current binding for Configuration::json passes a
nlohmann::json object into Python's json.dumps (and the stub claims dict
return), which fails because there is no nanobind caster and dumps returns a
string; change the lambda in the .def("json", ...) for class Configuration to
call Python's json.loads on config.json().dump() (i.e., convert the C++
nlohmann::json to a string via dump() and then call
nb::module_::import_("json").attr("loads") on that string) so the binding
returns a proper Python dict rather than attempting to pass the C++ json object
directly.
📜 Review details
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (5)
bindings/clifford_synthesis/clifford_synthesis.cppbindings/hybrid_mapper/hybrid_mapper.cppbindings/na/nasp/nasp.cppbindings/na/zoned/zoned.cppbindings/sc/sc.cpp
🧰 Additional context used
🧠 Learnings (14)
📓 Common learnings
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1383
File: bindings/dd/register_matrix_dds.cpp:64-109
Timestamp: 2025-12-15T01:54:22.129Z
Learning: In the munich-quantum-toolkit/core repository, after migrating to nanobind, docstrings for Python bindings are now added directly in the C++ binding code (using R"pb(...)pb" syntax) and stub files (.pyi) are auto-generated using the `bindings/generate-stubs.sh` script. This replaces the previous pybind11 approach where docstrings were manually maintained in stub files.
Learnt from: burgholzer
Repo: munich-quantum-toolkit/qcec PR: 817
File: pyproject.toml:81-82
Timestamp: 2026-01-09T17:58:10.350Z
Learning: In the Munich Quantum Toolkit projects using nanobind, setting `wheel.py-api = "cp312"` in `[tool.scikit-build]` enables Stable ABI wheels only for Python 3.12+ (where nanobind supports it), while automatically building regular non-ABI3 wheels for earlier Python versions (3.10, 3.11) and free-threading builds (3.14t). This allows a single configuration to appropriately handle both old and new Python versions without forcing incompatible ABI requirements.
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1383
File: bindings/ir/register_permutation.cpp:153-171
Timestamp: 2025-12-22T01:25:21.609Z
Learning: In the munich-quantum-toolkit/core repository, when using nanobind iterator factory functions like `make_key_iterator` and `make_iterator`, the unqualified form (without explicit `nb::` prefix) is preferred. The clang-tidy configuration suggests removal of explicit namespace qualification, relying on ADL (Argument-Dependent Lookup) to resolve these functions correctly.
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1355
File: bindings/fomac/fomac.cpp:227-264
Timestamp: 2025-12-07T01:21:27.544Z
Learning: In the munich-quantum-toolkit/core repository, docstrings for Python bindings are added to the corresponding stub files (.pyi) rather than directly in the pybind11 C++ bindings code. This practice may change if the project adopts nanobind with automatic stub generation.
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1383
File: bindings/fomac/fomac.cpp:111-116
Timestamp: 2025-12-19T00:05:54.428Z
Learning: In the munich-quantum-toolkit/core repository after migrating to nanobind, lifetime management differs from pybind11: `nb::keep_alive<nurse, patient>()` does not exist in nanobind. Instead, use `nb::rv_policy::reference_internal` when binding methods that return objects referencing internal state of the parent object (e.g., Session::getDevices returning Device objects that depend on the Session). This tells nanobind to keep the parent alive while children exist.
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1383
File: python/mqt/core/ir/operations.pyi:9-16
Timestamp: 2025-12-15T01:59:17.023Z
Learning: In the munich-quantum-toolkit/core repository, stub files (.pyi) are auto-generated by nanobind's stubgen tool and should not be manually modified for style preferences, as changes would be overwritten during regeneration.
📚 Learning: 2025-12-15T01:54:22.129Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1383
File: bindings/dd/register_matrix_dds.cpp:64-109
Timestamp: 2025-12-15T01:54:22.129Z
Learning: In the munich-quantum-toolkit/core repository, after migrating to nanobind, docstrings for Python bindings are now added directly in the C++ binding code (using R"pb(...)pb" syntax) and stub files (.pyi) are auto-generated using the `bindings/generate-stubs.sh` script. This replaces the previous pybind11 approach where docstrings were manually maintained in stub files.
Applied to files:
bindings/na/zoned/zoned.cppbindings/clifford_synthesis/clifford_synthesis.cppbindings/na/nasp/nasp.cppbindings/hybrid_mapper/hybrid_mapper.cppbindings/sc/sc.cpp
📚 Learning: 2025-12-19T00:05:54.428Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1383
File: bindings/fomac/fomac.cpp:111-116
Timestamp: 2025-12-19T00:05:54.428Z
Learning: In the munich-quantum-toolkit/core repository after migrating to nanobind, lifetime management differs from pybind11: `nb::keep_alive<nurse, patient>()` does not exist in nanobind. Instead, use `nb::rv_policy::reference_internal` when binding methods that return objects referencing internal state of the parent object (e.g., Session::getDevices returning Device objects that depend on the Session). This tells nanobind to keep the parent alive while children exist.
Applied to files:
bindings/na/zoned/zoned.cppbindings/na/nasp/nasp.cppbindings/hybrid_mapper/hybrid_mapper.cppbindings/sc/sc.cpp
📚 Learning: 2025-12-22T01:25:21.609Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1383
File: bindings/ir/register_permutation.cpp:153-171
Timestamp: 2025-12-22T01:25:21.609Z
Learning: In the munich-quantum-toolkit/core repository, when using nanobind iterator factory functions like `make_key_iterator` and `make_iterator`, the unqualified form (without explicit `nb::` prefix) is preferred. The clang-tidy configuration suggests removal of explicit namespace qualification, relying on ADL (Argument-Dependent Lookup) to resolve these functions correctly.
Applied to files:
bindings/na/zoned/zoned.cppbindings/clifford_synthesis/clifford_synthesis.cppbindings/na/nasp/nasp.cppbindings/hybrid_mapper/hybrid_mapper.cppbindings/sc/sc.cpp
📚 Learning: 2025-12-04T06:59:40.314Z
Learnt from: MatthiasReumann
Repo: munich-quantum-toolkit/core PR: 1301
File: mlir/lib/Dialect/MQTOpt/Transforms/Transpilation/LayeredUnit.cpp:84-85
Timestamp: 2025-12-04T06:59:40.314Z
Learning: In the MQTOpt MLIR routing passes (NaiveRoutingPassSC, AStarRoutingPassSC), the input IR is guaranteed to contain only 1-qubit and 2-qubit gates. All 3+-qubit gates must be decomposed before routing; otherwise the input IR is invalid. This invariant allows skipTwoQubitBlock in LayeredUnit.cpp to safely assert wires.size() == 2.
Applied to files:
bindings/na/zoned/zoned.cpp
📚 Learning: 2025-12-07T01:21:27.544Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1355
File: bindings/fomac/fomac.cpp:227-264
Timestamp: 2025-12-07T01:21:27.544Z
Learning: In the munich-quantum-toolkit/core repository, docstrings for Python bindings are added to the corresponding stub files (.pyi) rather than directly in the pybind11 C++ bindings code. This practice may change if the project adopts nanobind with automatic stub generation.
Applied to files:
bindings/clifford_synthesis/clifford_synthesis.cppbindings/na/nasp/nasp.cppbindings/hybrid_mapper/hybrid_mapper.cppbindings/sc/sc.cpp
📚 Learning: 2025-11-05T09:23:46.540Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1287
File: src/qdmi/dd/Device.cpp:492-521
Timestamp: 2025-11-05T09:23:46.540Z
Learning: In the munich-quantum-toolkit/core repository, the `qasm3::Importer::imports()` function is backwards compatible with OpenQASM 2 programs. Therefore, it can be used to parse both QASM2 and QASM3 program formats without requiring separate importers for each version.
Applied to files:
bindings/clifford_synthesis/clifford_synthesis.cpp
📚 Learning: 2025-12-07T09:10:31.836Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1355
File: src/qdmi/sc/Device.cpp:97-102
Timestamp: 2025-12-07T09:10:31.836Z
Learning: In the munich-quantum-toolkit/core repository, duplication of QDMI-related macros (such as IS_INVALID_ARGUMENT) across device implementations (e.g., in src/qdmi/sc/Device.cpp and src/qdmi/dd/Device.cpp) is acceptable as a temporary measure. The preferred long-term solution is to upstream these macros to the QDMI repository rather than creating local shared headers, so they can be reused across all dependent projects.
Applied to files:
bindings/clifford_synthesis/clifford_synthesis.cpp
📚 Learning: 2025-12-21T22:35:08.572Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1383
File: bindings/fomac/fomac.cpp:348-364
Timestamp: 2025-12-21T22:35:08.572Z
Learning: In the munich-quantum-toolkit/core repository's nanobind bindings, use `.sig("...")` on parameter arguments that have vector or container defaults (e.g., `"sites"_a.sig("...") = std::vector<fomac::Session::Device::Site>{}`) to prevent exposing mutable defaults in the Python API, which would be flagged as a code smell by Python linters. This pattern is preferred over removing `.sig("...")` even though it shows `...` in the stub signature.
Applied to files:
bindings/na/nasp/nasp.cppbindings/sc/sc.cpp
📚 Learning: 2025-10-09T13:14:10.178Z
Learnt from: DRovara
Repo: munich-quantum-toolkit/core PR: 1108
File: mlir/lib/Dialect/MQTOpt/Transforms/ReplaceBasisStateControlsWithIfPattern.cpp:219-221
Timestamp: 2025-10-09T13:14:10.178Z
Learning: The MQT Core project (munich-quantum-toolkit/core repository) uses the C++20 standard, not C++17. C++20 features such as abbreviated function templates (e.g., `const auto&` parameters) are supported and valid in this codebase.
Applied to files:
bindings/na/nasp/nasp.cpp
📚 Learning: 2025-12-28T17:14:53.890Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1403
File: src/qdmi/na/CMakeLists.txt:31-38
Timestamp: 2025-12-28T17:14:53.890Z
Learning: In the munich-quantum-toolkit/core repository, the NA device generator target (mqt-core-qdmi-na-device-gen) is intentionally propagated to MQT_CORE_TARGETS via list(APPEND) because it's publicly linked to the NA device library (the NA device uses a public function from the generator). The SC device generator is not propagated because it has no such dependency with the SC device library.
Applied to files:
bindings/na/nasp/nasp.cpp
📚 Learning: 2025-12-15T01:59:17.023Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1383
File: python/mqt/core/ir/operations.pyi:9-16
Timestamp: 2025-12-15T01:59:17.023Z
Learning: In the munich-quantum-toolkit/core repository, stub files (.pyi) are auto-generated by nanobind's stubgen tool and should not be manually modified for style preferences, as changes would be overwritten during regeneration.
Applied to files:
bindings/hybrid_mapper/hybrid_mapper.cppbindings/sc/sc.cpp
📚 Learning: 2025-11-20T18:19:31.857Z
Learnt from: lsschmid
Repo: munich-quantum-toolkit/qmap PR: 832
File: src/hybridmap/HybridNeutralAtomMapper.cpp:1679-1715
Timestamp: 2025-11-20T18:19:31.857Z
Learning: In src/hybridmap/HybridNeutralAtomMapper.cpp, the compareSwapAndBridge and compareShuttlingAndFlyingAncilla methods intentionally use division by zero to produce infinity when distance reductions are zero or negative. This infinity value marks that option as highly unfavorable in cost comparisons, which is the intended behavior rather than a bug.
Applied to files:
bindings/hybrid_mapper/hybrid_mapper.cpp
📚 Learning: 2025-11-27T08:52:06.428Z
Learnt from: lsschmid
Repo: munich-quantum-toolkit/qmap PR: 832
File: src/hybridmap/HybridNeutralAtomMapper.cpp:1379-1383
Timestamp: 2025-11-27T08:52:06.428Z
Learning: In src/hybridmap/HybridNeutralAtomMapper.cpp, the getBestMovePos function throws std::runtime_error when no move position is found (finalBestPos.coords is empty). This behavior is acceptable for current use cases since tight architectures are not a concern. A future improvement would be to fall back to SWAP-based strategies instead of throwing.
Applied to files:
bindings/hybrid_mapper/hybrid_mapper.cpp
🧬 Code graph analysis (3)
bindings/na/zoned/zoned.cpp (4)
test/na/zoned/test_heuristic_placer.cpp (3)
architecture(224-224)architecture(246-246)architecture(268-268)python/mqt/qmap/na/state_preparation.pyi (1)
json(82-87)include/na/zoned/Architecture.hpp (2)
json(229-230)json(237-238)python/mqt/qmap/na/zoned.pyi (2)
stats(139-144)stats(234-239)
bindings/na/nasp/nasp.cpp (1)
python/mqt/qmap/na/state_preparation.pyi (2)
solve(89-139)json(82-87)
bindings/hybrid_mapper/hybrid_mapper.cpp (2)
src/hybridmap/NeutralAtomArchitecture.cpp (2)
loadJson(41-157)loadJson(41-41)python/mqt/qmap/hybrid_mapper.pyi (1)
MapperParameters(24-40)
🪛 Cppcheck (2.19.0)
bindings/na/zoned/zoned.cpp
[information] 21-21: Include file
(missingIncludeSystem)
[information] 22-22: Include file
(missingIncludeSystem)
[information] 23-23: Include file
(missingIncludeSystem)
[information] 24-24: Include file
(missingIncludeSystem)
[information] 25-25: Include file
(missingIncludeSystem)
[information] 26-26: Include file
(missingIncludeSystem)
[information] 27-27: Include file
(missingIncludeSystem)
[information] 28-28: Include file
(missingIncludeSystem)
[information] 29-29: Include file
(missingIncludeSystem)
[information] 21-21: Include file
(missingIncludeSystem)
[information] 22-22: Include file
(missingIncludeSystem)
[information] 23-23: Include file
(missingIncludeSystem)
[information] 24-24: Include file
(missingIncludeSystem)
[information] 25-25: Include file
(missingIncludeSystem)
[information] 26-26: Include file
(missingIncludeSystem)
[information] 27-27: Include file
(missingIncludeSystem)
[information] 28-28: Include file
(missingIncludeSystem)
[information] 29-29: Include file
(missingIncludeSystem)
[information] 30-30: Include file
(missingIncludeSystem)
[information] 31-31: Include file
(missingIncludeSystem)
[information] 32-32: Include file
(missingIncludeSystem)
[information] 21-21: Include file
(missingIncludeSystem)
[information] 22-22: Include file
(missingIncludeSystem)
[information] 23-23: Include file
(missingIncludeSystem)
[information] 21-21: Include file
(missingIncludeSystem)
[information] 22-22: Include file
(missingIncludeSystem)
[information] 23-23: Include file
(missingIncludeSystem)
[information] 24-24: Include file
(missingIncludeSystem)
[information] 25-25: Include file
(missingIncludeSystem)
[information] 26-26: Include file
(missingIncludeSystem)
[information] 27-27: Include file
(missingIncludeSystem)
[information] 21-21: Include file
(missingInclude)
[information] 21-21: Include file
(missingIncludeSystem)
[information] 22-22: Include file
(missingIncludeSystem)
[information] 25-25: Include file
(missingIncludeSystem)
[information] 26-26: Include file
(missingIncludeSystem)
[information] 27-27: Include file
(missingIncludeSystem)
[information] 28-28: Include file
(missingIncludeSystem)
[information] 29-29: Include file
(missingIncludeSystem)
[information] 30-30: Include file
(missingIncludeSystem)
[information] 31-31: Include file
(missingIncludeSystem)
[information] 21-21: Include file
(missingIncludeSystem)
[information] 22-22: Include file
(missingIncludeSystem)
[information] 23-23: Include file
(missingIncludeSystem)
[information] 27-27: Include file
(missingIncludeSystem)
[information] 28-28: Include file
(missingIncludeSystem)
[information] 29-29: Include file
(missingIncludeSystem)
[style] 70-70: The function 'isStorage' is never used.
(unusedFunction)
bindings/clifford_synthesis/clifford_synthesis.cpp
[information] 20-20: Include file
(missingIncludeSystem)
[information] 21-21: Include file
(missingIncludeSystem)
[information] 22-22: Include file
(missingIncludeSystem)
[information] 23-23: Include file
(missingIncludeSystem)
[information] 20-20: Include file
(missingIncludeSystem)
[information] 21-21: Include file
(missingIncludeSystem)
[information] 22-22: Include file
(missingIncludeSystem)
[information] 23-23: Include file
(missingIncludeSystem)
[information] 24-24: Include file
(missingIncludeSystem)
[information] 25-25: Include file
(missingIncludeSystem)
[information] 26-26: Include file
(missingIncludeSystem)
[information] 20-20: Include file
(missingIncludeSystem)
[information] 21-21: Include file
(missingIncludeSystem)
[information] 20-20: Include file
(missingIncludeSystem)
[information] 20-20: Include file
(missingIncludeSystem)
[information] 20-20: Include file
(missingIncludeSystem)
[information] 21-21: Include file
(missingIncludeSystem)
[information] 21-21: Include file
(missingIncludeSystem)
[information] 22-22: Include file
(missingIncludeSystem)
[information] 23-23: Include file
(missingIncludeSystem)
[information] 24-24: Include file
(missingIncludeSystem)
[information] 25-25: Include file
(missingIncludeSystem)
[information] 26-26: Include file
(missingIncludeSystem)
[information] 20-20: Include file
(missingIncludeSystem)
[information] 21-21: Include file
(missingIncludeSystem)
[information] 22-22: Include file
(missingIncludeSystem)
[information] 23-23: Include file
(missingIncludeSystem)
[information] 24-24: Include file
(missingIncludeSystem)
[information] 25-25: Include file
(missingIncludeSystem)
[information] 20-20: Include file
(missingIncludeSystem)
[information] 21-21: Include file
(missingIncludeSystem)
[information] 22-22: Include file
(missingIncludeSystem)
[information] 23-23: Include file
(missingIncludeSystem)
[information] 24-24: Include file
(missingIncludeSystem)
[information] 20-20: Include file
(missingIncludeSystem)
[information] 21-21: Include file
(missingIncludeSystem)
[information] 22-22: Include file
(missingIncludeSystem)
[information] 23-23: Include file
(missingIncludeSystem)
[information] 24-24: Include file
(missingIncludeSystem)
[information] 25-25: Include file
(missingIncludeSystem)
[information] 26-26: Include file
(missingIncludeSystem)
[error] 176-176: Boolean value assigned to pointer.
(assignBoolToPointer)
[style] 76-76: The function 'requiresMultiGateEncoding' is never used.
(unusedFunction)
[style] 100-100: The function 'runBinarySearch' is never used.
(unusedFunction)
[style] 123-123: The function 'runLinearSearch' is never used.
(unusedFunction)
[style] 48-48: The function 'setSingleQubitGates' is never used.
(unusedFunction)
[style] 49-49: The function 'setTwoQubitGates' is never used.
(unusedFunction)
[style] 50-50: The function 'setDepth' is never used.
(unusedFunction)
[style] 51-51: The function 'setRuntime' is never used.
(unusedFunction)
[style] 52-52: The function 'setSolverResult' is never used.
(unusedFunction)
[style] 53-53: The function 'setSolverCalls' is never used.
(unusedFunction)
[style] 82-82: The function 'getTableau' is never used.
(unusedFunction)
[style] 96-96: The function 'containsX' is never used.
(unusedFunction)
[style] 99-99: The function 'containsY' is never used.
(unusedFunction)
[style] 102-102: The function 'containsZ' is never used.
(unusedFunction)
[style] 105-105: The function 'containsH' is never used.
(unusedFunction)
[style] 108-108: The function 'containsS' is never used.
(unusedFunction)
[style] 111-111: The function 'containsSdag' is never used.
(unusedFunction)
[style] 34-34: The function 'limitGateCount' is never used.
(unusedFunction)
[style] 66-66: The function 'collectSingleQubitGateTerms' is never used.
(unusedFunction)
[style] 80-80: The function 'collectTwoQubitGateTerms' is never used.
(unusedFunction)
[style] 72-72: The function 'getVariables' is never used.
(unusedFunction)
[style] 160-160: The function 'cTypeFromString' is never used.
(unusedFunction)
[style] 185-185: The function 'isArith' is never used.
(unusedFunction)
[style] 199-199: The function 'isNumber' is never used.
(unusedFunction)
[style] 210-210: The function 'isCommutative' is never used.
(unusedFunction)
[style] 39-39: The function 'getModel' is never used.
(unusedFunction)
[style] 135-135: The function 'getID' is never used.
(unusedFunction)
[style] 136-136: The function 'getNodes' is never used.
(unusedFunction)
[style] 137-137: The function 'getOpType' is never used.
(unusedFunction)
[style] 138-138: The function 'getCType' is never used.
(unusedFunction)
[style] 139-139: The function 'getName' is never used.
(unusedFunction)
[style] 140-140: The function 'getLogic' is never used.
(unusedFunction)
[style] 190-190: The function 'reset' is never used.
(unusedFunction)
bindings/na/nasp/nasp.cpp
[information] 19-19: Include file
(missingIncludeSystem)
[information] 20-20: Include file
(missingIncludeSystem)
[information] 21-21: Include file
(missingIncludeSystem)
[information] 22-22: Include file
(missingIncludeSystem)
[information] 23-23: Include file
(missingIncludeSystem)
[information] 24-24: Include file
(missingIncludeSystem)
[information] 19-19: Include file
(missingIncludeSystem)
[information] 20-20: Include file
(missingIncludeSystem)
[information] 21-21: Include file
(missingIncludeSystem)
[information] 22-22: Include file
(missingIncludeSystem)
[information] 23-23: Include file
(missingIncludeSystem)
[information] 24-24: Include file
(missingIncludeSystem)
[information] 25-25: Include file
(missingIncludeSystem)
[error] 42-42: Boolean value assigned to pointer.
(assignBoolToPointer)
[error] 42-42: Boolean value assigned to pointer.
(assignBoolToPointer)
bindings/hybrid_mapper/hybrid_mapper.cpp
[information] 20-20: Include file
(missingIncludeSystem)
[information] 21-21: Include file
(missingIncludeSystem)
[information] 20-20: Include file
(missingIncludeSystem)
[information] 21-21: Include file
(missingIncludeSystem)
[information] 22-22: Include file
(missingIncludeSystem)
[information] 23-23: Include file
(missingIncludeSystem)
[information] 24-24: Include file
(missingIncludeSystem)
[information] 25-25: Include file
(missingIncludeSystem)
[information] 26-26: Include file
(missingIncludeSystem)
[information] 20-20: Include file
(missingInclude)
[information] 22-22: Include file
(missingIncludeSystem)
[information] 23-23: Include file
(missingIncludeSystem)
[information] 24-24: Include file
(missingIncludeSystem)
[information] 25-25: Include file
(missingIncludeSystem)
[information] 26-26: Include file
(missingIncludeSystem)
[information] 27-27: Include file
(missingIncludeSystem)
[information] 28-28: Include file
(missingIncludeSystem)
[information] 29-29: Include file
(missingIncludeSystem)
[information] 30-30: Include file
(missingIncludeSystem)
[information] 31-31: Include file
(missingIncludeSystem)
[information] 32-32: Include file
(missingIncludeSystem)
[information] 33-33: Include file
(missingIncludeSystem)
[information] 34-34: Include file
(missingIncludeSystem)
[information] 35-35: Include file
(missingIncludeSystem)
[information] 36-36: Include file
(missingIncludeSystem)
[information] 21-21: Include file
(missingIncludeSystem)
[information] 22-22: Include file
(missingIncludeSystem)
[information] 23-23: Include file
(missingIncludeSystem)
[information] 24-24: Include file
(missingIncludeSystem)
[information] 25-25: Include file
(missingIncludeSystem)
[information] 26-26: Include file
(missingIncludeSystem)
[information] 27-27: Include file
(missingIncludeSystem)
[information] 28-28: Include file
(missingIncludeSystem)
[information] 29-29: Include file
(missingIncludeSystem)
[information] 30-30: Include file
(missingIncludeSystem)
[information] 31-31: Include file
(missingIncludeSystem)
[information] 20-20: Include file
(missingInclude)
[information] 21-21: Include file
(missingInclude)
[information] 23-23: Include file
(missingIncludeSystem)
[information] 24-24: Include file
(missingIncludeSystem)
[information] 25-25: Include file
(missingIncludeSystem)
[information] 26-26: Include file
(missingIncludeSystem)
[information] 27-27: Include file
(missingIncludeSystem)
[information] 28-28: Include file
(missingIncludeSystem)
[information] 20-20: Include file
(missingIncludeSystem)
[information] 21-21: Include file
(missingIncludeSystem)
[information] 20-20: Include file
(missingIncludeSystem)
[information] 21-21: Include file
(missingIncludeSystem)
[information] 22-22: Include file
(missingIncludeSystem)
[information] 23-23: Include file
(missingIncludeSystem)
[information] 24-24: Include file
(missingIncludeSystem)
[information] 25-25: Include file
(missingIncludeSystem)
[information] 26-26: Include file
(missingIncludeSystem)
[information] 27-27: Include file
(missingIncludeSystem)
[information] 21-21: Include file
(missingInclude)
[information] 22-22: Include file
(missingInclude)
[information] 24-24: Include file
(missingIncludeSystem)
[information] 25-25: Include file
(missingIncludeSystem)
[information] 26-26: Include file
(missingIncludeSystem)
[information] 27-27: Include file
(missingIncludeSystem)
[information] 28-28: Include file
(missingIncludeSystem)
[information] 29-29: Include file
(missingIncludeSystem)
[information] 30-30: Include file
(missingIncludeSystem)
[information] 31-31: Include file
(missingIncludeSystem)
[information] 32-32: Include file
(missingIncludeSystem)
[information] 33-33: Include file
(missingIncludeSystem)
[information] 34-34: Include file
(missingIncludeSystem)
[information] 35-35: Include file
(missingIncludeSystem)
[information] 23-23: Include file
(missingInclude)
[information] 24-24: Include file
(missingInclude)
[information] 26-26: Include file
(missingIncludeSystem)
[information] 27-27: Include file
(missingIncludeSystem)
[information] 28-28: Include file
(missingIncludeSystem)
[information] 29-29: Include file
(missingIncludeSystem)
[information] 30-30: Include file
(missingIncludeSystem)
[information] 31-31: Include file
(missingIncludeSystem)
[information] 20-20: Include file
(missingIncludeSystem)
[information] 21-21: Include file
(missingIncludeSystem)
[information] 22-22: Include file
(missingIncludeSystem)
[information] 23-23: Include file
(missingIncludeSystem)
[information] 24-24: Include file
(missingIncludeSystem)
[information] 25-25: Include file
(missingIncludeSystem)
[information] 26-26: Include file
(missingIncludeSystem)
[information] 27-27: Include file
(missingIncludeSystem)
[performance] 105-105: Function 'getGates()' should return member 'gates' by const reference.
(returnByReference)
[performance] 112-112: Function 'getNewGates()' should return member 'newGates' by const reference.
(returnByReference)
[style] 113-113: The function 'setCircuitQubit' is never used.
(unusedFunction)
[style] 136-136: The function 'getHwQubits' is never used.
(unusedFunction)
[style] 105-105: The function 'getGates' is never used.
(unusedFunction)
[style] 112-112: The function 'getNewGates' is never used.
(unusedFunction)
[style] 71-71: The function 'toCsv' is never used.
(unusedFunction)
[performance] 155-155: Function 'getAnimationViz()' should return member 'animation' by const reference.
(returnByReference)
[style] 215-215: The function 'mapToCoordIdx' is never used.
(unusedFunction)
bindings/sc/sc.cpp
[information] 34-34: Include file
(missingIncludeSystem)
[information] 35-35: Include file
(missingIncludeSystem)
[information] 36-36: Include file
(missingIncludeSystem)
[information] 37-37: Include file
(missingIncludeSystem)
[information] 38-38: Include file
(missingIncludeSystem)
[information] 39-39: Include file
(missingIncludeSystem)
[information] 40-40: Include file
(missingIncludeSystem)
[information] 41-41: Include file
(missingIncludeSystem)
[information] 42-42: Include file
(missingIncludeSystem)
[performance] 112-112: Prefer prefix ++/-- operators for non-primitive types.
(postfixOperator)
[style] 124-124: The function 'twoQubitErrorRateAvailable' is never used.
(unusedFunction)
[style] 111-111: The function 'dataLoggingEnabled' is never used.
(unusedFunction)
[style] 115-115: The function 'setTimeout' is never used.
(unusedFunction)
[style] 116-116: The function 'swapLimitsEnabled' is never used.
(unusedFunction)
[style] 124-124: The function 'getTotalFixedCost' is never used.
(unusedFunction)
[style] 120-120: The function 'update' is never used.
(unusedFunction)
[style] 140-140: The function 'restart' is never used.
(unusedFunction)
[style] 245-245: The function 'isEdgeConnected' is never used.
(unusedFunction)
[style] 253-253: The function 'isEdgeBidirectional' is never used.
(unusedFunction)
[style] 259-259: The function 'getDistanceTable' is never used.
(unusedFunction)
[style] 275-275: The function 'isFidelityAvailable' is never used.
(unusedFunction)
[style] 277-277: The function 'getFidelityDistanceTables' is never used.
(unusedFunction)
[style] 323-323: The function 'getFidelityTable' is never used.
(unusedFunction)
[style] 330-330: The function 'getSingleQubitFidelities' is never used.
(unusedFunction)
[style] 314-314: The function 'printLayering' is never used.
(unusedFunction)
[style] 330-330: The function 'printLocations' is never used.
(unusedFunction)
[style] 228-228: The function 'getConsideredQubits' is never used.
(unusedFunction)
[style] 405-405: The function 'isCalibrationDataAvailable' is never used.
(unusedFunction)
[style] 427-427: The function 'distance' is never used.
(unusedFunction)
[style] 411-411: The function 'computeEffectiveBranchingRate' is never used.
(unusedFunction)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (16)
- GitHub Check: 🇨 Test 🍎 (macos-14, clang, Debug) / 🍎 macos-14 clang Debug
- GitHub Check: 🐍 Test (ubuntu-24.04-arm) / 🐍 ubuntu-24.04-arm
- GitHub Check: 🐍 Test (macos-14) / 🐍 macos-14
- GitHub Check: 🐍 Test (macos-15-intel) / 🐍 macos-15-intel
- GitHub Check: 🇨 Test 🍎 (macos-15-intel, clang, Release) / 🍎 macos-15-intel clang Release
- GitHub Check: 🐍 Test (windows-2022) / 🐍 windows-2022
- GitHub Check: 🇨 Test 🏁 (windows-11-arm, msvc, Release) / 🏁 windows-11-arm msvc Release
- GitHub Check: 🐍 Test (ubuntu-24.04) / 🐍 ubuntu-24.04
- GitHub Check: 🇨 Test 🍎 (macos-14, clang, Release) / 🍎 macos-14 clang Release
- GitHub Check: 🇨 Test 🐧 (ubuntu-24.04, gcc, Release) / 🐧 ubuntu-24.04 gcc Release
- GitHub Check: 🇨 Test 🐧 (ubuntu-24.04, gcc, Debug) / 🐧 ubuntu-24.04 gcc Debug
- GitHub Check: 🇨 Test 🐧 (ubuntu-24.04-arm, gcc, Release) / 🐧 ubuntu-24.04-arm gcc Release
- GitHub Check: 🇨 Test 🏁 (windows-2022, msvc, Debug) / 🏁 windows-2022 msvc Debug
- GitHub Check: 🇨 Test 🏁 (windows-2022, msvc, Release) / 🏁 windows-2022 msvc Release
- GitHub Check: 🇨 Lint / 🚨 Lint
- GitHub Check: 🇨 Coverage / 📈 Coverage
🔇 Additional comments (33)
bindings/na/nasp/nasp.cpp (3)
19-24: LGTM!The nanobind includes are correctly structured with appropriate STL type converters. The
NOLINT(misc-include-cleaner)annotations are appropriate since these headers enable automatic type conversions even when not explicitly referenced in this translation unit.
27-31: LGTM!The module registration follows the established nanobind migration pattern. The
nb::module_::import_("mqt.core.ir")correctly ensures type dependencies (e.g.,QuantumComputation) are available before registering bindings that use them.
34-42: LGTM!The class binding is correctly migrated to nanobind syntax. The default argument specifications (
nb::none()for optional parameters, boolean defaults) are correct.Note: The Cppcheck "assignBoolToPointer" warning on line 42 is a false positive — the
"arg"_a = falsesyntax is valid nanobind usage where_areturns annb::argobject that accepts default values viaoperator=.bindings/na/zoned/zoned.cpp (8)
21-32: LGTM!The nanobind includes and namespace setup are correct. The NOLINT comments for
misc-include-cleanerare appropriate since these STL headers are used implicitly for automatic type conversions.
34-36: LGTM!The explicit
nb::module_::import_("mqt.core.ir")is essential for nanobind's cross-module type recognition. This ensures that types likeqc::QuantumComputationfrom the core module are properly resolved at runtime.
55-68: LGTM!The enum bindings correctly use nanobind's
nb::enum_. The absence of.export_values()is appropriate—nanobind does not export enum values to the enclosing scope by default, which aligns with Python's standard enum access pattern (e.g.,PlacementMethod.astar).
77-98: LGTM!The
__init__binding correctly uses nanobind's placement-new pattern. Thenb::keep_alive<1, 2>()appropriately ensures the architecture remains alive while the compiler exists, which is necessary since the compiler holds a reference to the architecture. Based on learnings, this is the correct nanobind pattern for lifetime management.
131-137: Acceptable JSON conversion pattern.The
json.loads(stats.dump())pattern correctly convertsnlohmann::jsonto a Python dict without requiringpybind11_json. The per-call module import is a minor overhead but acceptable for a statistics retrieval method that's typically not called in tight loops.
146-183: LGTM!The
RoutingAwareCompilerbinding follows the same correct patterns asRoutingAgnosticCompiler. The additional configuration parameters are properly exposed with appropriate defaults fromdefaultConfig, and thenb::keep_alive<1, 2>()ensures correct lifetime management.
233-239: LGTM!The stats method implementation is consistent with
RoutingAgnosticCompiler.
38-53: LGTM!The
Architectureclass binding correctly uses nanobind'snb::class_with appropriate method bindings for JSON file/string operations and NAMachine export functionality.bindings/clifford_synthesis/clifford_synthesis.cpp (6)
20-29: LGTM!The nanobind includes and namespace setup follow standard conventions. The
NOLINT(misc-include-cleaner)comments are appropriate since these STL headers enable implicit type conversions that are used indirectly.
31-40: LGTM!The
NB_MODULEmacro and enum binding are correctly structured. The import ofmqt.core.irensures the dependency module is loaded before using its types.
42-50: LGTM!The
plog::Severityenum is correctly bound with descriptive docstrings for each verbosity level.
53-143: LGTM!The
SynthesisConfigurationclass binding correctly usesdef_rwfor read-write properties and properly handles JSON serialization via Python'sjson.dumps(). Based on learnings, docstrings are correctly included directly in the C++ binding code as per the nanobind migration pattern.
146-171: LGTM!The
SynthesisResultsclass binding correctly usesdef_prop_rofor read-only properties. The getter methods return primitive types and strings by value, so no special return value policies are needed.
173-186: LGTM!The
Tableauclass binding correctly uses multiplenb::initoverloads for different constructors. The static analysis warning about "Boolean value assigned to pointer" at line 176 is a false positive—"include_destabilizers"_a = falseis standard nanobind syntax for specifying a default argument value.bindings/hybrid_mapper/hybrid_mapper.cpp (8)
20-34: LGTM! Nanobind setup follows established patterns.The include migration, namespace alias, and module declaration correctly follow the nanobind conventions. The explicit
nb::module_::import_("mqt.core.ir")ensures dependent types are registered before use. Based on learnings from the munich-quantum-toolkit/core migration.
37-48: LGTM! Enum bindings correctly migrated.The enum bindings properly use
nb::enum_<>without.export_values()(not needed in nanobind) and include docstrings directly in the binding code per the project's nanobind migration pattern.
50-102: LGTM! Class bindings use correct nanobind syntax.The
def_rwusage correctly replaces pybind11'sdef_readwrite, and all fields include descriptive docstrings. The bindings match the expected Python interface from the stub file.
104-152: LGTM! Architecture bindings properly use read-only and read-write properties.The use of
def_prop_rofor computed/immutable properties (dimensions, configuration values) anddef_rwfor the mutablenamefield correctly reflects the intended access patterns.
215-226: LGTM! HybridSynthesisMapper bindings follow consistent patterns.The constructor correctly uses
constreferences and appliesnb::keep_alivefor lifetime safety. The default parameter valuena::MapperParameters()is properly handled.
268-282: LGTM! Matrix conversion correctly bridges C++ and Python types.The lambda converts the internal
SymmetricMatrixtype to astd::vector<std::vector<int>>which nanobind can automatically convert to a Python list of lists. This is the expected pattern for exposing matrix data to Python.
1-310: Overall: Clean migration from pybind11 to nanobind.The binding code correctly applies nanobind idioms throughout:
NB_MODULEmacro with proper NOLINT suppressiondef_rw/def_prop_roreplacing pybind11'sdef_readwrite/def_property_readonlynb::keep_alive<>for lifetime management of stored references- Explicit module import for dependent types
- Docstrings embedded directly in C++ (per project conventions after nanobind migration)
The static analysis warnings are false positives—they reference missing system includes (expected in isolated analysis) and unused functions in unrelated source files.
Note: The PR description indicates the test coverage checklist item is incomplete. Consider adding tests to verify the binding behavior, especially for edge cases around lifetime management.
154-165: Fix binding signature to match C++ constructor:const na::MapperParameters&instead ofna::MapperParameters&.The C++ constructor takes
const MapperParameters& pand copies the parameters into a member variable (not storing a reference). The binding declaresna::MapperParameters&(non-const), which doesn't match the actual C++ API and incorrectly suggests the mapper keeps a reference to the caller's parameters.Additionally,
nb::keep_alive<1, 3>()is unnecessary—since parameters are copied, there's no lifetime dependency. Keepnb::keep_alive<1, 2>()for the architecture pointer, which is stored as-is.⛔ Skipped due to learnings
Learnt from: denialhaag Repo: munich-quantum-toolkit/core PR: 1383 File: bindings/fomac/fomac.cpp:111-116 Timestamp: 2025-12-19T00:05:54.428Z Learning: In the munich-quantum-toolkit/core repository after migrating to nanobind, lifetime management differs from pybind11: `nb::keep_alive<nurse, patient>()` does not exist in nanobind. Instead, use `nb::rv_policy::reference_internal` when binding methods that return objects referencing internal state of the parent object (e.g., Session::getDevices returning Device objects that depend on the Session). This tells nanobind to keep the parent alive while children exist.Learnt from: burgholzer Repo: munich-quantum-toolkit/core PR: 1383 File: bindings/fomac/fomac.cpp:348-364 Timestamp: 2025-12-21T22:35:08.572Z Learning: In the munich-quantum-toolkit/core repository's nanobind bindings, use `.sig("...")` on parameter arguments that have vector or container defaults (e.g., `"sites"_a.sig("...") = std::vector<fomac::Session::Device::Site>{}`) to prevent exposing mutable defaults in the Python API, which would be flagged as a code smell by Python linters. This pattern is preferred over removing `.sig("...")` even though it shows `...` in the stub signature.Learnt from: lsschmid Repo: munich-quantum-toolkit/qmap PR: 832 File: src/hybridmap/HybridNeutralAtomMapper.cpp:1379-1383 Timestamp: 2025-11-27T08:52:06.428Z Learning: In src/hybridmap/HybridNeutralAtomMapper.cpp, the getBestMovePos function throws std::runtime_error when no move position is found (finalBestPos.coords is empty). This behavior is acceptable for current use cases since tight architectures are not a concern. A future improvement would be to fall back to SWAP-based strategies instead of throwing.Learnt from: burgholzer Repo: munich-quantum-toolkit/core PR: 1383 File: bindings/ir/register_permutation.cpp:153-171 Timestamp: 2025-12-22T01:25:21.609Z Learning: In the munich-quantum-toolkit/core repository, when using nanobind iterator factory functions like `make_key_iterator` and `make_iterator`, the unqualified form (without explicit `nb::` prefix) is preferred. The clang-tidy configuration suggests removal of explicit namespace qualification, relying on ADL (Argument-Dependent Lookup) to resolve these functions correctly.Learnt from: lsschmid Repo: munich-quantum-toolkit/qmap PR: 832 File: src/hybridmap/HybridNeutralAtomMapper.cpp:1679-1715 Timestamp: 2025-11-20T18:19:31.857Z Learning: In src/hybridmap/HybridNeutralAtomMapper.cpp, the compareSwapAndBridge and compareShuttlingAndFlyingAncilla methods intentionally use division by zero to produce infinity when distance reductions are zero or negative. This infinity value marks that option as highly unfavorable in cost comparisons, which is the intended behavior rather than a bug.bindings/sc/sc.cpp (8)
34-45: LGTM!The nanobind includes and namespace setup follow the expected conventions. The NOLINT comments for STL type casters are appropriate since these headers enable automatic type conversion in bindings even when not explicitly referenced.
47-78: LGTM!The helper function is pure C++ logic unaffected by the binding library migration. Exception handling and move semantics are correctly applied.
80-172: LGTM!The module definition and enum bindings are correctly migrated to nanobind. The
NB_MODULEmacro, module import, andnb::enum_usage all follow nanobind conventions properly.
224-245: LGTM!The
MappingResultsclass binding is correctly migrated usingnb::class_,nb::init<>(), anddef_rw. The JSON serialization follows the same pattern established forConfiguration.
248-263: LGTM!The
CircuitInfonested class binding is correctly migrated. Properties are properly exposed usingdef_rw.
266-283: LGTM!The
HeuristicBenchmarkInfoclass binding is correctly migrated with proper use ofnb::class_,nb::init<>(), anddef_rw.
286-320: LGTM!The
LayerHeuristicBenchmarkInfoclass binding is correctly migrated with all benchmark properties properly exposed.
450-452: LGTM!The main mapping function binding is straightforward and correctly uses nanobind's argument annotation syntax.
burgholzer
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great besides the one small oversight 😌
Co-authored-by: Lukas Burgholzer <[email protected]> Signed-off-by: Daniel Haag <[email protected]>
Thank you for catching the incorrect PR number! 🙂 |
Description
This PR fully replaces
pybind11withnanobind. This change will allow us to ship Stable ABI wheels, saving us PyPI space.Checklist:
I have added appropriate tests that cover the new/changed functionality.