Skip to content

Conversation

@ystade
Copy link
Collaborator

@ystade ystade commented Nov 24, 2025

Description

This PR adds a—for the moment—minimalistic SC QDMI device that only features a coupling map. The changes extend the QDMI device framework by relocating the Device class to the qdmi::na namespace, adding a new superconducting (SC) device backend with session and job management APIs, introducing JSON-based device configuration and code generation utilities, and providing a CLI tool and comprehensive test coverage for the SC device.

Checklist:

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

@ystade ystade added this to the QDMI Support milestone Nov 24, 2025
@ystade ystade self-assigned this Nov 24, 2025
@ystade ystade added feature New feature or request c++ Anything related to C++ code QDMI Anything related to QDMI labels Nov 24, 2025
@ystade
Copy link
Collaborator Author

ystade commented Nov 24, 2025

I am aware of the code duplicates between the NA and SC device originating from a lot of copy paste. This PR is meant to provide a first initial implementation for @MatthiasReumann to test his QMAP implementation with a QDMI device. I do plan to refactor this initial implementation at a later point. If ok, I would like to merge this initial PR rather quickly and simultaneously open a tracking issue to polish this initial implementation.
@burgholzer what do you say?

@ystade
Copy link
Collaborator Author

ystade commented Nov 24, 2025

While working on this PR, it might also an idea to move the NA QDMI device to the QDMI directory, @burgholzer ? Should I open an issue for that as well?

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 24, 2025

📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Added support for a superconducting quantum device backend featuring 100 qubits with configurable coupling topology
    • Introduced device configuration tools including schema generation, JSON validation, and C++ header code generation
    • Extended device library management to support multiple device backends simultaneously

✏️ Tip: You can customize this high-level summary in your review settings.

Walkthrough

Moved NA Device into namespace qdmi::na and converted several NA job methods to instance methods. Added a full SC QDMI backend (generator, CLI, static/dynamic libraries, C API, header generation from a 100‑qubit JSON), integrated SC into Driver/CMake, and added tests and test CMake updates.

Changes

Cohort / File(s) Summary
NA Device namespace & API
include/mqt-core/na/device/Device.hpp, src/na/device/Device.cpp
Moved Device into qdmi::na; updated singleton references (initialize(), finalize(), get(), std::atomic<Device*> instance) and adjusted call sites.
NA job instance methods
include/mqt-core/na/device/Device.hpp
Converted MQT_NA_QDMI_Device_Job_impl_d methods from static to instance methods: setParameter, queryProperty, submit, cancel, check, wait, getResults (all return int).
SC device core & C API
include/mqt-core/qdmi/sc/Device.hpp, src/qdmi/sc/Device.cpp, src/qdmi/sc/DynDevice.cpp
Added SC backend: singleton Device, session/job/site/operation impl_d types, full C API entry points, job lifecycle implementations (many NOTSUPPORTED defaults), and dynamic-wrapper forwarding (with special NAME handling).
SC generator & model
include/mqt-core/qdmi/sc/Generator.hpp, src/qdmi/sc/Generator.cpp, json/sc/device.json
Added sc::Device type with JSON (de)serialization, read/write utilities, header emission (generator), and a default 100‑qubit device JSON model.
SC CLI & build
src/qdmi/sc/App.cpp, src/qdmi/sc/CMakeLists.txt, src/qdmi/CMakeLists.txt
New CLI (schema/validate/generate) and CMake targets/aliases for generator and SC device (static and optional dynamic), header generation and integration into qdmi build.
Driver integration
include/mqt-core/qdmi/Driver.hpp, src/qdmi/Driver.cpp
Declared/defined SC static library via macros, wired SC into Driver construction, tightened session cleanup, and added MQT::CoreQDMIScDevice linking.
Tests & test CMake updates
test/qdmi/*, test/qdmi/CMakeLists.txt, test/qdmi/sc/*, test/qdmi/test_driver.cpp
Added generator/CLI/SC device tests; updated test CMake to register multiple dynamic device libs; expanded device lists and updated driver tests to iterate dynamic libs.
NA test renames & test fixes
test/na/device/*, test/fomac/test_fomac.cpp, test/python/fomac/test_fomac.py
Renamed NA test suites/fixtures to Na* prefixes; FoMaC tests and Python fixture adjusted to use vectors/guards to avoid empty-index issues.
CMake / misc build/help fixes
src/qdmi/CMakeLists.txt, src/na/device/App.cpp, assorted tests
Added sc subdir to qdmi CMake, included missing <tuple> include, tightened help text formatting, and minor test signature updates.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant Client
    participant Driver
    participant SC_Device as "MQT_SC Device (singleton)"
    participant Session
    participant Job

    Client->>Driver: load/register device libraries
    Driver->>SC_Device: register static SC library
    Client->>SC_Device: initialize()
    Client->>SC_Device: sessionAlloc() → Session
    Client->>Session: init() / setParameter(...)
    Client->>Session: createDeviceJob() → Job
    Client->>Job: setParameter(...), submit()
    Job->>SC_Device: submit processed (NOTSUPPORTED or queued)
    Client->>Job: check()/wait()/get_results()
    Client->>SC_Device: sessionFree(Session)
    Client->>SC_Device: finalize()
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

  • Focus review on:
    • include/mqt-core/qdmi/sc/Device.hpp and src/qdmi/sc/Device.cpp (lifecycle, impl_d types, property handling, C API surface).
    • src/qdmi/sc/DynDevice.cpp (ABI/forwarding safety and NAME buffer handling).
    • include/mqt-core/na/device/Device.hpp and src/na/device/Device.cpp (namespace move, atomic singleton, changed job method bindings).
    • CMake changes (src/qdmi/sc/CMakeLists.txt, src/qdmi/CMakeLists.txt, test/qdmi/CMakeLists.txt) for header generation ordering, new targets/aliases, and platform conditionals.
    • Tests that register multiple dynamic libs and renamed fixtures—ensure test targets and names align.

Possibly related PRs

Suggested reviewers

  • ystade

Poem

🐰 I hopped through headers and changed a name with glee,
I tucked the singleton in qdmi::na snugly,
SC devices sprouted from JSON and code,
Sessions and jobs now follow the new road,
I nibble specs and hum — this commit's a treat 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 27.04% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: adding a new QDMI device for superconducting (SC) devices. It accurately reflects the primary objective without noise or vague terminology.
Description check ✅ Passed The PR description follows the template with a clear summary, addresses all checklist items (marked complete), and provides context about the changes including namespace relocation, new SC backend, JSON configuration, CLI tool, and tests.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch ystade/qdmi-sc-device

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 66b7938 and 6434dd9.

📒 Files selected for processing (1)
  • test/fomac/test_fomac.cpp (2 hunks)
🧰 Additional context used
🧠 Learnings (6)
📓 Common learnings
Learnt from: marcelwa
Repo: munich-quantum-toolkit/core PR: 1243
File: test/python/qdmi/qiskit/test_qdmi_qiskit_backend.py:0-0
Timestamp: 2025-11-04T14:28:32.371Z
Learning: In the munich-quantum-toolkit/core repository, at least one FoMaC device is always available during testing, so skip logic for missing devices in QDMI Qiskit backend tests is not necessary.
Learnt from: marcelwa
Repo: munich-quantum-toolkit/core PR: 1243
File: test/python/qdmi/qiskit/test_qdmi_qiskit_site_handling.py:162-173
Timestamp: 2025-10-17T11:09:50.147Z
Learning: For QDMI tests that reference a specific named device via fixture (e.g., "MQT NA Default QDMI Device"), it is acceptable to hard-code device-specific values such as zone counts and indices, as these tests are intentionally coupled to that device's structure and serve as structural invariant checks.
📚 Learning: 2025-11-26T10:29:36.435Z
Learnt from: marcelwa
Repo: munich-quantum-toolkit/core PR: 1243
File: test/python/fomac/test_fomac.py:54-66
Timestamp: 2025-11-26T10:29:36.435Z
Learning: In test/python/fomac/test_fomac.py, the `ddsim_device` fixture returns `Device | None` even though it only returns a `Device` or calls `pytest.skip()`. The `| None` annotation is required for the type checker to pass, as type checkers may not recognize `pytest.skip()` as a function that never returns.

Applied to files:

  • test/fomac/test_fomac.cpp
📚 Learning: 2025-11-04T14:28:32.371Z
Learnt from: marcelwa
Repo: munich-quantum-toolkit/core PR: 1243
File: test/python/qdmi/qiskit/test_qdmi_qiskit_backend.py:0-0
Timestamp: 2025-11-04T14:28:32.371Z
Learning: In the munich-quantum-toolkit/core repository, at least one FoMaC device is always available during testing, so skip logic for missing devices in QDMI Qiskit backend tests is not necessary.

Applied to files:

  • test/fomac/test_fomac.cpp
📚 Learning: 2025-10-09T13:20:11.483Z
Learnt from: DRovara
Repo: munich-quantum-toolkit/core PR: 1108
File: mlir/test/Dialect/MQTOpt/Transforms/lift-measurements.mlir:269-288
Timestamp: 2025-10-09T13:20:11.483Z
Learning: In the MQT MLIR dialect, the `rz` gate should not be included in the `DIAGONAL_GATES` set for the `ReplaceBasisStateControlsWithIfPattern` because its operator matrix does not have the required shape | 1 0 | / | 0 x | for the targets-as-controls optimization. It is only included in `LiftMeasurementsAboveGatesPatterns` where the matrix structure requirement differs.

Applied to files:

  • test/fomac/test_fomac.cpp
📚 Learning: 2025-11-01T15:57:31.153Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1283
File: src/qir/runtime/QIR.cpp:196-201
Timestamp: 2025-11-01T15:57:31.153Z
Learning: In the QIR runtime (src/qir/runtime/QIR.cpp), the PRX gate (__quantum__qis__prx__body) is an alias for the R gate (Phased X-Rotation) and should call runtime.apply<qc::R>(theta, phi, qubit), not runtime.apply<qc::RX>() which is a single-parameter rotation gate.

Applied to files:

  • test/fomac/test_fomac.cpp
📚 Learning: 2025-10-17T11:09:50.147Z
Learnt from: marcelwa
Repo: munich-quantum-toolkit/core PR: 1243
File: test/python/qdmi/qiskit/test_qdmi_qiskit_site_handling.py:162-173
Timestamp: 2025-10-17T11:09:50.147Z
Learning: For QDMI tests that reference a specific named device via fixture (e.g., "MQT NA Default QDMI Device"), it is acceptable to hard-code device-specific values such as zone counts and indices, as these tests are intentionally coupled to that device's structure and serve as structural invariant checks.

Applied to files:

  • test/fomac/test_fomac.cpp
🧬 Code graph analysis (1)
test/fomac/test_fomac.cpp (3)
include/mqt-core/fomac/FoMaC.hpp (9)
  • sites (493-495)
  • sites (498-500)
  • sites (503-504)
  • sites (507-509)
  • sites (512-514)
  • sites (517-519)
  • sites (522-524)
  • sites (527-529)
  • sites (549-551)
include/mqt-core/na/fomac/Device.hpp (1)
  • device (122-123)
src/na/device/Device.cpp (2)
  • site (356-356)
  • site (364-364)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: 🐍 Test (macos-14) / 🐍 macos-14
  • GitHub Check: 🐍 Test (macos-15-intel) / 🐍 macos-15-intel
  • GitHub Check: 🐍 Test (ubuntu-24.04) / 🐍 ubuntu-24.04
  • GitHub Check: 🐍 Test (windows-2022) / 🐍 windows-2022
🔇 Additional comments (8)
test/fomac/test_fomac.cpp (8)

34-39: LGTM!

The refactor from a single Site to std::vector<Site> with a straightforward assignment in SetUp is clean and avoids the previous null-dereference issues. The DeviceTest::Sites test at line 229 validates that devices have sites.


41-46: LGTM!

Consistent refactor pattern matching SiteTest. The vector-based approach is straightforward and safe.


265-341: LGTM!

The site property tests correctly iterate over all sites and verify each getter can be invoked without throwing. The pattern is consistent and straightforward.


343-359: LGTM!

The basic operation property tests follow the established pattern correctly.


361-431: LGTM!

The branching logic correctly handles all operation configurations:

  • Operations without qubitsNum fall back to the generic call
  • 1-qubit operations test per-site duration/fidelity when sites are available
  • 2-qubit operations test per-site-pair duration/fidelity when site pairs are available
  • All other cases use the generic call

The duplication between Duration and Fidelity was discussed in past reviews and deferred to a planned refactor.


451-455: Good rename!

The test name IsZoned now correctly reflects the method under test (operation.isZoned()), addressing a previous review comment.


463-485: LGTM with a minor observation.

The SitePairs test logic correctly validates:

  • Only 2-qubit non-zoned operations should have site pairs
  • Sites must exist with an even count for site pairs to be valid
  • Site pairs count should be half the sites count

Lines 480-483 use defensive coding with an if guard after EXPECT_TRUE. Since EXPECT_TRUE is non-fatal, this prevents a potential crash if the expectation fails. An alternative would be ASSERT_TRUE to make it fatal and remove the guard, but the current approach is reasonable for test robustness.


487-491: LGTM!

Consistent iteration pattern for MeanShuttlingSpeed.


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

❤️ Share

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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 18

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4d87628 and 2812858.

📒 Files selected for processing (19)
  • include/mqt-core/na/device/Device.hpp (2 hunks)
  • include/mqt-core/qdmi/Driver.hpp (1 hunks)
  • include/mqt-core/qdmi/sc/Device.hpp (1 hunks)
  • include/mqt-core/qdmi/sc/Generator.hpp (1 hunks)
  • json/sc/device.json (1 hunks)
  • src/na/device/Device.cpp (5 hunks)
  • src/qdmi/CMakeLists.txt (2 hunks)
  • src/qdmi/Driver.cpp (3 hunks)
  • src/qdmi/sc/App.cpp (1 hunks)
  • src/qdmi/sc/CMakeLists.txt (1 hunks)
  • src/qdmi/sc/Device.cpp (1 hunks)
  • src/qdmi/sc/DynDevice.cpp (1 hunks)
  • src/qdmi/sc/Generator.cpp (1 hunks)
  • test/qdmi/CMakeLists.txt (1 hunks)
  • test/qdmi/sc/CMakeLists.txt (1 hunks)
  • test/qdmi/sc/test_app.cpp (1 hunks)
  • test/qdmi/sc/test_device.cpp (1 hunks)
  • test/qdmi/sc/test_generator.cpp (1 hunks)
  • test/qdmi/test_driver.cpp (2 hunks)
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: marcelwa
Repo: munich-quantum-toolkit/core PR: 1243
File: test/python/qdmi/qiskit/test_qdmi_qiskit_backend.py:0-0
Timestamp: 2025-11-04T14:28:32.371Z
Learning: In the munich-quantum-toolkit/core repository, at least one FoMaC device is always available during testing, so skip logic for missing devices in QDMI Qiskit backend tests is not necessary.
Learnt from: marcelwa
Repo: munich-quantum-toolkit/core PR: 1243
File: test/python/qdmi/qiskit/test_qdmi_qiskit_site_handling.py:162-173
Timestamp: 2025-10-17T11:09:50.147Z
Learning: For QDMI tests that reference a specific named device via fixture (e.g., "MQT NA Default QDMI Device"), it is acceptable to hard-code device-specific values such as zone counts and indices, as these tests are intentionally coupled to that device's structure and serve as structural invariant checks.
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.
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1287
File: test/qdmi/dd/error_handling_test.cpp:118-194
Timestamp: 2025-11-05T07:42:45.507Z
Learning: In the munich-quantum-toolkit/core QDMI device API, session parameters can only be set before calling `device_session_init()`. Once a session is initialized, any attempt to set a parameter returns `QDMI_ERROR_BADSTATE`. Since `SessionGuard` (in test/qdmi/dd/helpers/test_utils.hpp) automatically initializes the session in its constructor, tests that need to verify session parameter setting behavior before initialization must allocate a separate uninitialized session rather than reusing the `SessionGuard`'s session.
📚 Learning: 2025-10-17T11:09:50.147Z
Learnt from: marcelwa
Repo: munich-quantum-toolkit/core PR: 1243
File: test/python/qdmi/qiskit/test_qdmi_qiskit_site_handling.py:162-173
Timestamp: 2025-10-17T11:09:50.147Z
Learning: For QDMI tests that reference a specific named device via fixture (e.g., "MQT NA Default QDMI Device"), it is acceptable to hard-code device-specific values such as zone counts and indices, as these tests are intentionally coupled to that device's structure and serve as structural invariant checks.

Applied to files:

  • json/sc/device.json
  • test/qdmi/sc/CMakeLists.txt
  • test/qdmi/CMakeLists.txt
  • include/mqt-core/na/device/Device.hpp
  • src/qdmi/sc/CMakeLists.txt
  • src/qdmi/Driver.cpp
  • src/na/device/Device.cpp
  • test/qdmi/sc/test_device.cpp
  • test/qdmi/test_driver.cpp
  • include/mqt-core/qdmi/sc/Device.hpp
  • src/qdmi/sc/Device.cpp
  • src/qdmi/sc/DynDevice.cpp
📚 Learning: 2025-11-04T14:28:32.371Z
Learnt from: marcelwa
Repo: munich-quantum-toolkit/core PR: 1243
File: test/python/qdmi/qiskit/test_qdmi_qiskit_backend.py:0-0
Timestamp: 2025-11-04T14:28:32.371Z
Learning: In the munich-quantum-toolkit/core repository, at least one FoMaC device is always available during testing, so skip logic for missing devices in QDMI Qiskit backend tests is not necessary.

Applied to files:

  • json/sc/device.json
  • test/qdmi/sc/CMakeLists.txt
  • src/qdmi/Driver.cpp
  • test/qdmi/sc/test_device.cpp
  • test/qdmi/test_driver.cpp
  • include/mqt-core/qdmi/sc/Device.hpp
📚 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:

  • include/mqt-core/qdmi/sc/Generator.hpp
  • test/qdmi/sc/CMakeLists.txt
  • test/qdmi/CMakeLists.txt
  • src/qdmi/sc/Generator.cpp
  • src/qdmi/sc/CMakeLists.txt
  • src/qdmi/CMakeLists.txt
  • src/qdmi/Driver.cpp
  • test/qdmi/sc/test_device.cpp
  • test/qdmi/test_driver.cpp
  • include/mqt-core/qdmi/sc/Device.hpp
  • src/qdmi/sc/Device.cpp
  • src/qdmi/sc/DynDevice.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:

  • test/qdmi/CMakeLists.txt
  • src/qdmi/sc/CMakeLists.txt
  • src/qdmi/CMakeLists.txt
📚 Learning: 2025-11-04T19:50:14.489Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1287
File: test/qdmi/dd/helpers/test_utils.cpp:103-118
Timestamp: 2025-11-04T19:50:14.489Z
Learning: In the munich-quantum-toolkit/core QDMI device tests, when QDMI APIs return a string result size `ks` that includes a null terminator, the pattern `std::string keys(ks - 1, '\0'); ... device_job_get_results(..., ks, keys.data(), nullptr)` is correct and safe. The string allocates `ks` bytes total (ks-1 content + implicit null), and the API writing `ks` bytes (including trailing null) fits exactly into this space without buffer overrun.

Applied to files:

  • include/mqt-core/na/device/Device.hpp
  • src/qdmi/Driver.cpp
  • test/qdmi/sc/test_device.cpp
📚 Learning: 2025-11-05T07:42:45.507Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1287
File: test/qdmi/dd/error_handling_test.cpp:118-194
Timestamp: 2025-11-05T07:42:45.507Z
Learning: In the munich-quantum-toolkit/core QDMI device API, session parameters can only be set before calling `device_session_init()`. Once a session is initialized, any attempt to set a parameter returns `QDMI_ERROR_BADSTATE`. Since `SessionGuard` (in test/qdmi/dd/helpers/test_utils.hpp) automatically initializes the session in its constructor, tests that need to verify session parameter setting behavior before initialization must allocate a separate uninitialized session rather than reusing the `SessionGuard`'s session.

Applied to files:

  • include/mqt-core/na/device/Device.hpp
  • src/na/device/Device.cpp
  • test/qdmi/sc/test_device.cpp
  • test/qdmi/test_driver.cpp
  • include/mqt-core/qdmi/sc/Device.hpp
  • src/qdmi/sc/Device.cpp
  • src/qdmi/sc/DynDevice.cpp
🧬 Code graph analysis (6)
include/mqt-core/qdmi/sc/Generator.hpp (2)
include/mqt-core/qdmi/sc/Device.hpp (1)
  • nodiscard (58-61)
src/qdmi/sc/Generator.cpp (2)
  • nodiscard (126-138)
  • nodiscard (140-149)
src/qdmi/sc/Generator.cpp (2)
include/mqt-core/qdmi/sc/Device.hpp (2)
  • id (239-240)
  • nodiscard (58-61)
include/mqt-core/qdmi/sc/Generator.hpp (6)
  • writeJSONSchema (56-56)
  • writeJSONSchema (65-65)
  • readJSON (74-74)
  • readJSON (83-83)
  • writeHeader (94-94)
  • writeHeader (105-105)
test/qdmi/sc/test_app.cpp (2)
test/qir/runtime/test_qir_runtime.cpp (1)
  • cout (37-37)
test/qdmi/sc/test_device.cpp (1)
  • ASSERT_EQ (56-68)
src/qdmi/sc/App.cpp (2)
include/mqt-core/qdmi/sc/Generator.hpp (6)
  • writeJSONSchema (56-56)
  • writeJSONSchema (65-65)
  • readJSON (74-74)
  • readJSON (83-83)
  • writeHeader (94-94)
  • writeHeader (105-105)
src/qdmi/sc/Generator.cpp (10)
  • writeJSONSchema (98-111)
  • writeJSONSchema (98-98)
  • writeJSONSchema (113-124)
  • writeJSONSchema (113-113)
  • readJSON (126-126)
  • readJSON (140-140)
  • writeHeader (151-157)
  • writeHeader (151-151)
  • writeHeader (159-169)
  • writeHeader (159-159)
include/mqt-core/qdmi/sc/Device.hpp (1)
include/mqt-core/na/device/Device.hpp (8)
  • Device (69-69)
  • Device (73-73)
  • Device (76-76)
  • Device (86-86)
  • session (92-92)
  • session (98-98)
  • id (280-283)
  • id (285-287)
src/qdmi/sc/DynDevice.cpp (1)
include/mqt-core/qdmi/sc/Device.hpp (13)
  • session (70-70)
  • session (76-76)
  • param (115-116)
  • param (183-184)
  • job (122-122)
  • job (128-128)
  • prop (82-83)
  • prop (134-135)
  • prop (190-191)
  • prop (245-246)
  • site (141-143)
  • operation (149-153)
  • numSites (266-269)
🪛 GitHub Check: 🇨‌ Lint / 🚨 Lint
src/qdmi/sc/Generator.cpp

[warning] 33-33: src/qdmi/sc/Generator.cpp:33:1 [misc-include-cleaner]
included header utility is not used directly


[warning] 32-32: src/qdmi/sc/Generator.cpp:32:1 [misc-include-cleaner]
included header tuple is not used directly


[warning] 27-27: src/qdmi/sc/Generator.cpp:27:1 [misc-include-cleaner]
included header ranges is not used directly


[warning] 23-23: src/qdmi/sc/Generator.cpp:23:1 [misc-include-cleaner]
included header functional is not used directly


[warning] 20-20: src/qdmi/sc/Generator.cpp:20:1 [misc-include-cleaner]
included header cstddef is not used directly


[warning] 17-17: src/qdmi/sc/Generator.cpp:17:1 [misc-include-cleaner]
included header algorithm is not used directly

test/qdmi/sc/test_device.cpp

[warning] 12-12: test/qdmi/sc/test_device.cpp:12:1 [misc-include-cleaner]
included header Generator.hpp is not used directly

src/qdmi/sc/Device.cpp

[warning] 292-292: src/qdmi/sc/Device.cpp:292:36 [readability-convert-member-functions-to-static]
method 'queryProperty' can be made static


[warning] 290-290: src/qdmi/sc/Device.cpp:290:57 [performance-move-const-arg]
std::move of the variable 'op' of the trivially-copyable type 'MQT_SC_QDMI_Operation_impl_d' has no effect; remove std::move()


[warning] 20-20: src/qdmi/sc/Device.cpp:20:1 [misc-include-cleaner]
included header algorithm is not used directly

⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: 🐍 Test (macos-15-intel) / 🐍 macos-15-intel
  • GitHub Check: 🐍 Test (macos-14) / 🐍 macos-14
  • GitHub Check: 🐍 Test (windows-2022) / 🐍 windows-2022
  • GitHub Check: 🇨‌ Test 🍎 (macos-15-intel, clang, Release) / 🍎 macos-15-intel clang Release
🔇 Additional comments (14)
json/sc/device.json (1)

1-186: Coupling map JSON is well-formed and index-safe

The numQubits and couplings list are consistent (indices stay within [0, 99] and form a regular 10×10 grid of nearest‑neighbor edges). No structural issues from the JSON side.

include/mqt-core/qdmi/Driver.hpp (1)

141-144: SC static device library declaration aligns with existing pattern

Adding DECLARE_STATIC_LIBRARY(MQT_SC) mirrors the NA and DDSIM declarations and cleanly extends the static backend list; just ensure the corresponding implementation (DEFINE_STATIC_LIBRARY(MQT_SC) or equivalent) is provided in the source so linkage succeeds.

test/qdmi/sc/CMakeLists.txt (1)

9-31: SC QDMI test target wiring is consistent with existing device-test patterns

The SC device test setup (guarded on SC targets existing, reuse of generate_device_defs_executable, dependency on qdmi_test_mqt_sc_device_defs, linking against CoreQDMIScDeviceGen and nlohmann_json, and passing EXECUTABLE_PATH/SC_DEVICE_JSON) looks coherent and in line with the existing QDMI device test infrastructure.

src/na/device/Device.cpp (1)

92-163: NA device implementation namespace move to qdmi::na is consistent and non-breaking

Wrapping Device in namespace qdmi::na and updating the few call sites (queryDeviceProperty, MQT_NA_QDMI_device_initialize, *_session_alloc/free) to use qdmi::na::Device::get() aligns the implementation with the header move without altering behavior. The global C API symbols remain unchanged.

Also applies to: 210-211, 561-581

include/mqt-core/na/device/Device.hpp (1)

29-107: NA Device declaration correctly moved into qdmi::na namespace

Placing Device in namespace qdmi::na (with the rest of the neutral-atom specifics) matches the implementation and keeps the QDMI core namespace less crowded; the surrounding QDMI impl structs remain at global scope as before, so the C API surface stays stable.

test/qdmi/sc/test_device.cpp (1)

52-348: SC device session/job coverage looks solid

The session/job lifecycle and property tests (including BADSTATE vs INVALIDARGUMENT vs NOTSUPPORTED cases) are consistent with the QDMI conventions and exercise the SC backend well.

src/qdmi/CMakeLists.txt (1)

10-10: SC device library is wired correctly into the QDMI driver

Adding add_subdirectory(sc) and linking MQT::CoreQDMIScDevice privately into the driver aligns with the existing NA and DDSIM wiring and keeps the public interface unchanged.

Also applies to: 29-30

src/qdmi/sc/App.cpp (1)

168-195: CLI parsing and command dispatch are well‑structured

The separation between global parsing (parseArguments), per‑command parsers, and execute* handlers, plus the defensive try/catch and logging around both argv handling and subcommand parsing, looks clean and robust.

Also applies to: 277-385, 399-446

src/qdmi/Driver.cpp (1)

15-15: SC static device library integration matches existing pattern

Including mqt_sc_qdmi/device.h, defining DEFINE_STATIC_LIBRARY(MQT_SC), and adding an MQT_SCDeviceLibrary instance in the Driver constructor mirror the established NA/DDSIM setup and cleanly expose the new SC backend to QDMI sessions.

Also applies to: 78-81, 335-343

src/qdmi/sc/CMakeLists.txt (1)

9-205: SC CMake wiring and header generation look consistent.

Targets, aliases, and header‑generation/custom‑command wiring match the QDMI patterns (including generate_prefixed_qdmi_headers and JSON‑driven header gen). Dependency ordering via add_dependencies(... generate_qdmi_sc_device_header) and versioning/export properties look good.

include/mqt-core/qdmi/sc/Device.hpp (1)

24-270: SC device interface mirrors existing QDMI patterns cleanly.

Singleton Device and the *_impl_d helper structs follow the established QDMI design (session/job/site/operation separation) and provide a clear, minimal public surface for SC devices. From the header alone, there are no obvious correctness or API‑shape issues.

src/qdmi/sc/Device.cpp (3)

92-151: Device construction and device-level property dispatch look consistent and robust

The singleton Device constructor and queryProperty implementation:

  • Correctly initialize name, qubit count, sites, and coupling map via the initializer helpers.
  • Validate arguments (value != nullptr && size == 0, enum range checks).
  • Use the helper macros to return proper sizes and types for device properties, including sites, coupling map, and operations.
  • Return QDMI_ERROR_NOTSUPPORTED for unhandled but in-range properties, which aligns well with a minimal device.

One thing to double-check outside this file is that operations_ is initialized consistently with the SC generator/config, but from this file’s perspective the plumbing is sound.


154-172: Session parameter state machine correctly enforces “only before init” rule

MQT_SC_QDMI_Device_Session_impl_d::init and setParameter:

  • Enforce that init() is only valid in the ALLOCATED state.
  • Enforce that setParameter is only allowed while status_ == Status::ALLOCATED, returning QDMI_ERROR_BADSTATE afterwards.
  • Validate arguments (value != nullptr && size == 0, parameter enum range).

This matches the documented QDMI behavior that session parameters can only be set before device_session_init() is called.

Based on learnings, this aligns with the expected session parameter semantics.


225-271: Guard against null job handles in MQT_SC_QDMI_device_job_free

Most job-related C API wrappers validate job == nullptr and return QDMI_ERROR_INVALIDARGUMENT, but MQT_SC_QDMI_device_job_free dereferences the handle unconditionally via job->free(). This will segfault if a caller ever passes a null job (or a stale pointer):

void MQT_SC_QDMI_device_job_free(MQT_SC_QDMI_Device_Job job) { job->free(); }

Since the function is void and cannot report an error, turning a null handle into a no-op is the safest behavior and consistent with sessionFree:

-void MQT_SC_QDMI_device_job_free(MQT_SC_QDMI_Device_Job job) { job->free(); }
+void MQT_SC_QDMI_device_job_free(MQT_SC_QDMI_Device_Job job) {
+  if (job != nullptr) {
+    job->free();
+  }
+}

This eliminates a potential null-pointer dereference in the public C API.

⛔ Skipped due to learnings
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1287
File: test/qdmi/dd/helpers/test_utils.cpp:103-118
Timestamp: 2025-11-04T19:50:14.489Z
Learning: In the munich-quantum-toolkit/core QDMI device tests, when QDMI APIs return a string result size `ks` that includes a null terminator, the pattern `std::string keys(ks - 1, '\0'); ... device_job_get_results(..., ks, keys.data(), nullptr)` is correct and safe. The string allocates `ks` bytes total (ks-1 content + implicit null), and the API writing `ks` bytes (including trailing null) fits exactly into this space without buffer overrun.
Learnt from: marcelwa
Repo: munich-quantum-toolkit/core PR: 1243
File: test/python/qdmi/qiskit/test_qdmi_qiskit_site_handling.py:162-173
Timestamp: 2025-10-17T11:09:50.147Z
Learning: For QDMI tests that reference a specific named device via fixture (e.g., "MQT NA Default QDMI Device"), it is acceptable to hard-code device-specific values such as zone counts and indices, as these tests are intentionally coupled to that device's structure and serve as structural invariant checks.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 24, 2025

Note

Docstrings generation - SUCCESS
Generated docstrings for this pull request at #1329

coderabbitai bot added a commit that referenced this pull request Nov 24, 2025
Docstrings generation was requested by @ystade.

* #1328 (comment)

The following files were modified:

* `include/mqt-core/qdmi/sc/Device.hpp`
* `src/na/device/Device.cpp`
* `src/qdmi/Driver.cpp`
* `src/qdmi/sc/App.cpp`
* `src/qdmi/sc/Device.cpp`
* `src/qdmi/sc/DynDevice.cpp`
* `src/qdmi/sc/Generator.cpp`
* `test/na/device/test_app.cpp`
* `test/na/device/test_device.cpp`
* `test/na/device/test_generator.cpp`
* `test/qdmi/sc/test_app.cpp`
* `test/qdmi/sc/test_device.cpp`
* `test/qdmi/sc/test_generator.cpp`
* `test/qdmi/test_driver.cpp`
@codecov
Copy link

codecov bot commented Nov 24, 2025

Codecov Report

❌ Patch coverage is 92.52577% with 29 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/qdmi/sc/Device.cpp 94.4% 13 Missing ⚠️
src/qdmi/sc/Generator.cpp 86.7% 11 Missing ⚠️
src/qdmi/sc/DynDevice.cpp 92.9% 4 Missing ⚠️
src/qdmi/Driver.cpp 75.0% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@burgholzer
Copy link
Member

I am aware of the code duplicates between the NA and SC device originating from a lot of copy paste. This PR is meant to provide a first initial implementation for @MatthiasReumann to test his QMAP implementation with a QDMI device. I do plan to refactor this initial implementation at a later point. If ok, I would like to merge this initial PR rather quickly and simultaneously open a tracking issue to polish this initial implementation. @burgholzer what do you say?

I am fine with moving rather quickly here.
I can prioritize the review here once CI is green.
A tracking issue would be appropriate.

Docstrings generation was requested by @ystade.

*
#1328 (comment)

The following files were modified:

* `include/mqt-core/qdmi/sc/Device.hpp`
* `src/na/device/Device.cpp`
* `src/qdmi/Driver.cpp`
* `src/qdmi/sc/App.cpp`
* `src/qdmi/sc/Device.cpp`
* `src/qdmi/sc/DynDevice.cpp`
* `src/qdmi/sc/Generator.cpp`
* `test/na/device/test_app.cpp`
* `test/na/device/test_device.cpp`
* `test/na/device/test_generator.cpp`
* `test/qdmi/sc/test_app.cpp`
* `test/qdmi/sc/test_device.cpp`
* `test/qdmi/sc/test_generator.cpp`
* `test/qdmi/test_driver.cpp`

<details>
<summary>These file types are not supported</summary>

* `json/sc/device.json`
* `src/qdmi/CMakeLists.txt`
* `src/qdmi/sc/CMakeLists.txt`
* `test/qdmi/CMakeLists.txt`
* `test/qdmi/sc/CMakeLists.txt`

</details>

<details>
<summary>ℹ️ Note</summary><blockquote>

CodeRabbit cannot perform edits on its own pull requests yet.

</blockquote></details>

Co-authored-by: Yannick Stade <100073938+ystade@users.noreply.github.com>
@burgholzer
Copy link
Member

While working on this PR, it might also an idea to move the NA QDMI device to the QDMI directory, @burgholzer ? Should I open an issue for that as well?

Yeah. I have thought about that as well.
Seems like a good idea to me. When working on the DD simulator device, it only felt right to put it where it is now. Moving the NA device accordingly makes sense.

@ystade ystade changed the title ✨ New QDMI Device to represetn SC Devices ✨ New QDMI Device to represent SC Devices Nov 24, 2025
@ystade ystade added enhancement New feature or request and removed feature New feature or request labels Nov 24, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

♻️ Duplicate comments (3)
src/qdmi/sc/App.cpp (1)

94-112: Fix generate usage string to match optional json_file argument

The usage line shows <json_file> as required, but the description and implementation treat it as optional (stdin fallback). The argument should be shown in square brackets [<json_file>] to match the behavior.

src/qdmi/sc/Generator.cpp (2)

11-13: Update @file description to refer to superconducting devices.

The file comment says "neutral atom devices" but this file is for SC devices. Should say "superconducting devices" or "SC devices".


17-35: Remove unused includes to satisfy misc-include-cleaner.

Static analysis flags several unused headers: algorithm, cstddef, functional, ranges, tuple, and utility. Removing them would silence warnings and improve build times.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8553ccb and 19e699b.

📒 Files selected for processing (3)
  • include/mqt-core/qdmi/sc/Device.hpp (1 hunks)
  • src/qdmi/sc/App.cpp (1 hunks)
  • src/qdmi/sc/Generator.cpp (1 hunks)
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: marcelwa
Repo: munich-quantum-toolkit/core PR: 1243
File: test/python/qdmi/qiskit/test_qdmi_qiskit_backend.py:0-0
Timestamp: 2025-11-04T14:28:32.371Z
Learning: In the munich-quantum-toolkit/core repository, at least one FoMaC device is always available during testing, so skip logic for missing devices in QDMI Qiskit backend tests is not necessary.
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.
📚 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:

  • src/qdmi/sc/Generator.cpp
  • include/mqt-core/qdmi/sc/Device.hpp
📚 Learning: 2025-10-17T11:09:50.147Z
Learnt from: marcelwa
Repo: munich-quantum-toolkit/core PR: 1243
File: test/python/qdmi/qiskit/test_qdmi_qiskit_site_handling.py:162-173
Timestamp: 2025-10-17T11:09:50.147Z
Learning: For QDMI tests that reference a specific named device via fixture (e.g., "MQT NA Default QDMI Device"), it is acceptable to hard-code device-specific values such as zone counts and indices, as these tests are intentionally coupled to that device's structure and serve as structural invariant checks.

Applied to files:

  • include/mqt-core/qdmi/sc/Device.hpp
📚 Learning: 2025-11-05T07:42:45.507Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1287
File: test/qdmi/dd/error_handling_test.cpp:118-194
Timestamp: 2025-11-05T07:42:45.507Z
Learning: In the munich-quantum-toolkit/core QDMI device API, session parameters can only be set before calling `device_session_init()`. Once a session is initialized, any attempt to set a parameter returns `QDMI_ERROR_BADSTATE`. Since `SessionGuard` (in test/qdmi/dd/helpers/test_utils.hpp) automatically initializes the session in its constructor, tests that need to verify session parameter setting behavior before initialization must allocate a separate uninitialized session rather than reusing the `SessionGuard`'s session.

Applied to files:

  • include/mqt-core/qdmi/sc/Device.hpp
📚 Learning: 2025-11-04T14:28:32.371Z
Learnt from: marcelwa
Repo: munich-quantum-toolkit/core PR: 1243
File: test/python/qdmi/qiskit/test_qdmi_qiskit_backend.py:0-0
Timestamp: 2025-11-04T14:28:32.371Z
Learning: In the munich-quantum-toolkit/core repository, at least one FoMaC device is always available during testing, so skip logic for missing devices in QDMI Qiskit backend tests is not necessary.

Applied to files:

  • include/mqt-core/qdmi/sc/Device.hpp
🧬 Code graph analysis (3)
src/qdmi/sc/Generator.cpp (2)
include/mqt-core/qdmi/sc/Device.hpp (2)
  • id (252-253)
  • nodiscard (62-65)
include/mqt-core/qdmi/sc/Generator.hpp (6)
  • writeJSONSchema (56-56)
  • writeJSONSchema (65-65)
  • readJSON (74-74)
  • readJSON (83-83)
  • writeHeader (94-94)
  • writeHeader (105-105)
src/qdmi/sc/App.cpp (2)
src/qdmi/sc/Generator.cpp (10)
  • writeJSONSchema (114-127)
  • writeJSONSchema (114-114)
  • writeJSONSchema (139-150)
  • writeJSONSchema (139-139)
  • readJSON (162-162)
  • readJSON (185-185)
  • writeHeader (207-213)
  • writeHeader (207-207)
  • writeHeader (225-235)
  • writeHeader (225-225)
include/mqt-core/qdmi/sc/Generator.hpp (6)
  • writeJSONSchema (56-56)
  • writeJSONSchema (65-65)
  • readJSON (74-74)
  • readJSON (83-83)
  • writeHeader (94-94)
  • writeHeader (105-105)
include/mqt-core/qdmi/sc/Device.hpp (1)
include/mqt-core/qdmi/Driver.hpp (5)
  • session (424-424)
  • session (430-430)
  • prop (220-221)
  • prop (283-284)
  • prop (363-364)
🪛 GitHub Check: 🇨‌ Lint / 🚨 Lint
src/qdmi/sc/Generator.cpp

[warning] 33-33: src/qdmi/sc/Generator.cpp:33:1 [misc-include-cleaner]
included header utility is not used directly


[warning] 32-32: src/qdmi/sc/Generator.cpp:32:1 [misc-include-cleaner]
included header tuple is not used directly


[warning] 27-27: src/qdmi/sc/Generator.cpp:27:1 [misc-include-cleaner]
included header ranges is not used directly


[warning] 23-23: src/qdmi/sc/Generator.cpp:23:1 [misc-include-cleaner]
included header functional is not used directly


[warning] 20-20: src/qdmi/sc/Generator.cpp:20:1 [misc-include-cleaner]
included header cstddef is not used directly


[warning] 17-17: src/qdmi/sc/Generator.cpp:17:1 [misc-include-cleaner]
included header algorithm is not used directly

⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: 🐍 Test (macos-15-intel) / 🐍 macos-15-intel
  • GitHub Check: 🐍 Test (windows-2022) / 🐍 windows-2022

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

♻️ Duplicate comments (3)
src/qdmi/sc/App.cpp (1)

94-112: Fix generate usage string to match optional json_file argument.

The usage line shows <json_file> as required, but both the description (lines 102-104) and parseGenerateArguments (lines 275-291) treat it as optional with stdin fallback.

Apply this diff to mark the argument as optional:

         "Usage: "
      << programName
-     << " generate [options] <json_file>\n"
+     << " generate [options] [<json_file>]\n"
src/qdmi/sc/Generator.cpp (2)

11-13: Update file description to refer to superconducting devices.

The file comment incorrectly refers to "neutral atom devices" but this file is in the sc/ directory and implements the SC device generator.

Apply this diff:

 /** @file
- * @brief The MQT QDMI device generator for neutral atom devices.
+ * @brief The MQT QDMI device generator for superconducting devices.
  */

17-35: Remove unused includes.

Static analysis flags several unused headers: algorithm, cstddef, functional, ranges, tuple, and utility.

Apply this diff:

 #include "qdmi/sc/Generator.hpp"
 
-#include <algorithm>
 #include <cassert>
 #include <cmath>
-#include <cstddef>
 #include <cstdint>
 #include <fstream>
-#include <functional>
 #include <istream>
 #include <nlohmann/json.hpp>
 #include <ostream>
-#include <ranges>
 #include <spdlog/spdlog.h>
 #include <sstream>
 #include <stdexcept>
 #include <string>
-#include <tuple>
-#include <utility>
 #include <vector>
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8553ccb and 19e699b.

📒 Files selected for processing (3)
  • include/mqt-core/qdmi/sc/Device.hpp (1 hunks)
  • src/qdmi/sc/App.cpp (1 hunks)
  • src/qdmi/sc/Generator.cpp (1 hunks)
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: marcelwa
Repo: munich-quantum-toolkit/core PR: 1243
File: test/python/qdmi/qiskit/test_qdmi_qiskit_backend.py:0-0
Timestamp: 2025-11-04T14:28:32.371Z
Learning: In the munich-quantum-toolkit/core repository, at least one FoMaC device is always available during testing, so skip logic for missing devices in QDMI Qiskit backend tests is not necessary.
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.
📚 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:

  • src/qdmi/sc/Generator.cpp
📚 Learning: 2025-10-17T11:09:50.147Z
Learnt from: marcelwa
Repo: munich-quantum-toolkit/core PR: 1243
File: test/python/qdmi/qiskit/test_qdmi_qiskit_site_handling.py:162-173
Timestamp: 2025-10-17T11:09:50.147Z
Learning: For QDMI tests that reference a specific named device via fixture (e.g., "MQT NA Default QDMI Device"), it is acceptable to hard-code device-specific values such as zone counts and indices, as these tests are intentionally coupled to that device's structure and serve as structural invariant checks.

Applied to files:

  • include/mqt-core/qdmi/sc/Device.hpp
📚 Learning: 2025-11-05T07:42:45.507Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1287
File: test/qdmi/dd/error_handling_test.cpp:118-194
Timestamp: 2025-11-05T07:42:45.507Z
Learning: In the munich-quantum-toolkit/core QDMI device API, session parameters can only be set before calling `device_session_init()`. Once a session is initialized, any attempt to set a parameter returns `QDMI_ERROR_BADSTATE`. Since `SessionGuard` (in test/qdmi/dd/helpers/test_utils.hpp) automatically initializes the session in its constructor, tests that need to verify session parameter setting behavior before initialization must allocate a separate uninitialized session rather than reusing the `SessionGuard`'s session.

Applied to files:

  • include/mqt-core/qdmi/sc/Device.hpp
📚 Learning: 2025-11-04T14:28:32.371Z
Learnt from: marcelwa
Repo: munich-quantum-toolkit/core PR: 1243
File: test/python/qdmi/qiskit/test_qdmi_qiskit_backend.py:0-0
Timestamp: 2025-11-04T14:28:32.371Z
Learning: In the munich-quantum-toolkit/core repository, at least one FoMaC device is always available during testing, so skip logic for missing devices in QDMI Qiskit backend tests is not necessary.

Applied to files:

  • include/mqt-core/qdmi/sc/Device.hpp
🧬 Code graph analysis (1)
src/qdmi/sc/App.cpp (1)
src/qdmi/sc/Generator.cpp (10)
  • writeJSONSchema (114-127)
  • writeJSONSchema (114-114)
  • writeJSONSchema (139-150)
  • writeJSONSchema (139-139)
  • readJSON (162-162)
  • readJSON (185-185)
  • writeHeader (207-213)
  • writeHeader (207-207)
  • writeHeader (225-235)
  • writeHeader (225-225)
🪛 GitHub Check: 🇨‌ Lint / 🚨 Lint
src/qdmi/sc/Generator.cpp

[warning] 33-33: src/qdmi/sc/Generator.cpp:33:1 [misc-include-cleaner]
included header utility is not used directly


[warning] 32-32: src/qdmi/sc/Generator.cpp:32:1 [misc-include-cleaner]
included header tuple is not used directly


[warning] 27-27: src/qdmi/sc/Generator.cpp:27:1 [misc-include-cleaner]
included header ranges is not used directly


[warning] 23-23: src/qdmi/sc/Generator.cpp:23:1 [misc-include-cleaner]
included header functional is not used directly


[warning] 20-20: src/qdmi/sc/Generator.cpp:20:1 [misc-include-cleaner]
included header cstddef is not used directly


[warning] 17-17: src/qdmi/sc/Generator.cpp:17:1 [misc-include-cleaner]
included header algorithm is not used directly

🔇 Additional comments (13)
src/qdmi/sc/App.cpp (5)

216-233: LGTM: Schema argument parsing is robust.

The function correctly handles help flags and output options with appropriate error handling for missing values.


302-331: LGTM: Schema command execution is well-structured.

The function properly handles argument parsing, help output, and schema generation with appropriate error handling and logging.


346-368: LGTM: Validate command execution is correct.

The function correctly validates JSON input from file or stdin, with appropriate error handling.


383-420: LGTM: Generate command execution is well-implemented.

The function properly reads device configuration from JSON and generates header output with appropriate error handling.


435-484: LGTM: Main function is well-structured with appropriate error handling.

The function correctly builds the argument vector, parses global options, handles help/version flags, and dispatches to the appropriate subcommand executor. The try-catch blocks ensure graceful error handling throughout.

src/qdmi/sc/Generator.cpp (4)

46-48: LGTM: Default array population for schema generation.

This helper correctly ensures the device has at least one coupling element for schema generation purposes.


114-150: LGTM: JSON schema writing is well-implemented.

Both the stream and file-based versions are correctly implemented with appropriate error handling and logging.


162-194: LGTM: JSON reading is well-implemented.

Both the stream and file-based versions correctly parse JSON with appropriate error handling.


207-235: LGTM: Header writing correctly maintains macro order dependency.

The function properly writes the header guard and device initialization macros in the correct order, maintaining the dependency between writeSites and writeCouplingMap.

include/mqt-core/qdmi/sc/Device.hpp (4)

62-88: LGTM: Device API is well-documented and follows QDMI patterns.

The public API correctly implements session management and property queries, with appropriate documentation references to the C API.


94-158: LGTM: Session implementation structure is well-designed.

The session implementation correctly tracks lifecycle state and manages job ownership with appropriate QDMI API methods.


237-260: LGTM: Site implementation uses factory pattern correctly.

The site implementation correctly encapsulates the ID and provides a factory function for creation, with appropriate property query support.


265-283: LGTM: Operation implementation structure is appropriate.

The operation implementation correctly uses a factory pattern and provides property query support with site and parameter arrays.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d6bc57d and b9f7722.

📒 Files selected for processing (7)
  • include/mqt-core/qdmi/sc/Device.hpp (1 hunks)
  • include/mqt-core/qdmi/sc/Generator.hpp (1 hunks)
  • json/sc/device.json (1 hunks)
  • src/qdmi/sc/Device.cpp (1 hunks)
  • src/qdmi/sc/Generator.cpp (1 hunks)
  • test/fomac/test_fomac.cpp (4 hunks)
  • test/qdmi/test_driver.cpp (4 hunks)
🧰 Additional context used
🧠 Learnings (9)
📓 Common learnings
Learnt from: marcelwa
Repo: munich-quantum-toolkit/core PR: 1243
File: test/python/qdmi/qiskit/test_qdmi_qiskit_backend.py:0-0
Timestamp: 2025-11-04T14:28:32.371Z
Learning: In the munich-quantum-toolkit/core repository, at least one FoMaC device is always available during testing, so skip logic for missing devices in QDMI Qiskit backend tests is not necessary.
Learnt from: marcelwa
Repo: munich-quantum-toolkit/core PR: 1243
File: test/python/qdmi/qiskit/test_qdmi_qiskit_site_handling.py:162-173
Timestamp: 2025-10-17T11:09:50.147Z
Learning: For QDMI tests that reference a specific named device via fixture (e.g., "MQT NA Default QDMI Device"), it is acceptable to hard-code device-specific values such as zone counts and indices, as these tests are intentionally coupled to that device's structure and serve as structural invariant checks.
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.
📚 Learning: 2025-11-26T10:29:36.435Z
Learnt from: marcelwa
Repo: munich-quantum-toolkit/core PR: 1243
File: test/python/fomac/test_fomac.py:54-66
Timestamp: 2025-11-26T10:29:36.435Z
Learning: In test/python/fomac/test_fomac.py, the `ddsim_device` fixture returns `Device | None` even though it only returns a `Device` or calls `pytest.skip()`. The `| None` annotation is required for the type checker to pass, as type checkers may not recognize `pytest.skip()` as a function that never returns.

Applied to files:

  • test/fomac/test_fomac.cpp
📚 Learning: 2025-11-04T14:28:32.371Z
Learnt from: marcelwa
Repo: munich-quantum-toolkit/core PR: 1243
File: test/python/qdmi/qiskit/test_qdmi_qiskit_backend.py:0-0
Timestamp: 2025-11-04T14:28:32.371Z
Learning: In the munich-quantum-toolkit/core repository, at least one FoMaC device is always available during testing, so skip logic for missing devices in QDMI Qiskit backend tests is not necessary.

Applied to files:

  • test/fomac/test_fomac.cpp
  • test/qdmi/test_driver.cpp
  • json/sc/device.json
  • src/qdmi/sc/Device.cpp
  • include/mqt-core/qdmi/sc/Device.hpp
📚 Learning: 2025-10-09T13:20:11.483Z
Learnt from: DRovara
Repo: munich-quantum-toolkit/core PR: 1108
File: mlir/test/Dialect/MQTOpt/Transforms/lift-measurements.mlir:269-288
Timestamp: 2025-10-09T13:20:11.483Z
Learning: In the MQT MLIR dialect, the `rz` gate should not be included in the `DIAGONAL_GATES` set for the `ReplaceBasisStateControlsWithIfPattern` because its operator matrix does not have the required shape | 1 0 | / | 0 x | for the targets-as-controls optimization. It is only included in `LiftMeasurementsAboveGatesPatterns` where the matrix structure requirement differs.

Applied to files:

  • test/fomac/test_fomac.cpp
📚 Learning: 2025-11-01T15:57:31.153Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1283
File: src/qir/runtime/QIR.cpp:196-201
Timestamp: 2025-11-01T15:57:31.153Z
Learning: In the QIR runtime (src/qir/runtime/QIR.cpp), the PRX gate (__quantum__qis__prx__body) is an alias for the R gate (Phased X-Rotation) and should call runtime.apply<qc::R>(theta, phi, qubit), not runtime.apply<qc::RX>() which is a single-parameter rotation gate.

Applied to files:

  • test/fomac/test_fomac.cpp
📚 Learning: 2025-10-17T11:09:50.147Z
Learnt from: marcelwa
Repo: munich-quantum-toolkit/core PR: 1243
File: test/python/qdmi/qiskit/test_qdmi_qiskit_site_handling.py:162-173
Timestamp: 2025-10-17T11:09:50.147Z
Learning: For QDMI tests that reference a specific named device via fixture (e.g., "MQT NA Default QDMI Device"), it is acceptable to hard-code device-specific values such as zone counts and indices, as these tests are intentionally coupled to that device's structure and serve as structural invariant checks.

Applied to files:

  • test/fomac/test_fomac.cpp
  • test/qdmi/test_driver.cpp
  • json/sc/device.json
  • src/qdmi/sc/Device.cpp
  • include/mqt-core/qdmi/sc/Device.hpp
📚 Learning: 2025-11-05T07:42:45.507Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1287
File: test/qdmi/dd/error_handling_test.cpp:118-194
Timestamp: 2025-11-05T07:42:45.507Z
Learning: In the munich-quantum-toolkit/core QDMI device API, session parameters can only be set before calling `device_session_init()`. Once a session is initialized, any attempt to set a parameter returns `QDMI_ERROR_BADSTATE`. Since `SessionGuard` (in test/qdmi/dd/helpers/test_utils.hpp) automatically initializes the session in its constructor, tests that need to verify session parameter setting behavior before initialization must allocate a separate uninitialized session rather than reusing the `SessionGuard`'s session.

Applied to files:

  • test/fomac/test_fomac.cpp
  • test/qdmi/test_driver.cpp
  • src/qdmi/sc/Device.cpp
  • include/mqt-core/qdmi/sc/Device.hpp
📚 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:

  • test/qdmi/test_driver.cpp
  • src/qdmi/sc/Generator.cpp
  • src/qdmi/sc/Device.cpp
  • include/mqt-core/qdmi/sc/Generator.hpp
  • include/mqt-core/qdmi/sc/Device.hpp
📚 Learning: 2025-11-04T19:50:14.489Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1287
File: test/qdmi/dd/helpers/test_utils.cpp:103-118
Timestamp: 2025-11-04T19:50:14.489Z
Learning: In the munich-quantum-toolkit/core QDMI device tests, when QDMI APIs return a string result size `ks` that includes a null terminator, the pattern `std::string keys(ks - 1, '\0'); ... device_job_get_results(..., ks, keys.data(), nullptr)` is correct and safe. The string allocates `ks` bytes total (ks-1 content + implicit null), and the API writing `ks` bytes (including trailing null) fits exactly into this space without buffer overrun.

Applied to files:

  • test/qdmi/test_driver.cpp
  • src/qdmi/sc/Device.cpp
🧬 Code graph analysis (4)
test/fomac/test_fomac.cpp (2)
include/mqt-core/fomac/FoMaC.hpp (9)
  • sites (493-495)
  • sites (498-500)
  • sites (503-504)
  • sites (507-509)
  • sites (512-514)
  • sites (517-519)
  • sites (522-524)
  • sites (527-529)
  • sites (549-551)
src/na/device/Device.cpp (2)
  • site (356-356)
  • site (364-364)
src/qdmi/sc/Generator.cpp (2)
include/mqt-core/qdmi/sc/Generator.hpp (6)
  • device (111-111)
  • device (122-122)
  • os (73-73)
  • path (82-82)
  • path (100-100)
  • is (91-91)
include/mqt-core/qdmi/sc/Device.hpp (1)
  • id (266-267)
src/qdmi/sc/Device.cpp (2)
include/mqt-core/qdmi/sc/Device.hpp (11)
  • prop (100-101)
  • prop (152-153)
  • prop (213-214)
  • prop (272-273)
  • Device (52-52)
  • Device (59-59)
  • Device (62-62)
  • Device (66-66)
  • session (88-88)
  • session (94-94)
  • id (266-267)
src/qdmi/Driver.cpp (8)
  • sessionAlloc (369-377)
  • sessionAlloc (369-369)
  • sessionFree (379-383)
  • sessionFree (379-379)
  • queryProperty (260-264)
  • queryProperty (260-261)
  • queryDeviceProperty (190-195)
  • queryDeviceProperty (190-192)
include/mqt-core/qdmi/sc/Generator.hpp (1)
src/qdmi/sc/Generator.cpp (2)
  • nodiscard (179-191)
  • nodiscard (202-211)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: 🐍 Test (windows-2022) / 🐍 windows-2022
  • GitHub Check: 🐍 Test (ubuntu-24.04) / 🐍 ubuntu-24.04
  • GitHub Check: 🐍 Test (macos-15-intel) / 🐍 macos-15-intel
🔇 Additional comments (5)
test/fomac/test_fomac.cpp (1)

17-17: LGTM! Refactor to unique_ptr pattern correctly implemented.

The refactor from value members to std::unique_ptr<Site> and std::unique_ptr<Operation> is correctly implemented:

  • #include <memory> added appropriately.
  • SetUp() initializes the pointers via std::make_unique after asserting non-empty collections, avoiding null dereferences.
  • All test methods consistently use -> operator.
  • Hard assertions (ASSERT_FALSE(sites.empty()) / ASSERT_FALSE(operations.empty())) align with the maintainer's confirmed expectation that all FoMaC devices must have sites and operations.

Based on past review comments, the null-dereference concern was addressed and operations were added to the SC device per burgholzer's request.

Also applies to: 37-54, 274-372

include/mqt-core/qdmi/sc/Generator.hpp (1)

1-123: LGTM!

The Generator header is well-structured with:

  • Complete includes (including for std::pair)
  • Clear Device schema with proper JSON serialization macros
  • Comprehensive API for JSON schema generation, reading, and header writing
  • Good documentation with doxygen comments

All past review concerns have been addressed.

src/qdmi/sc/Generator.cpp (1)

1-254: LGTM!

The Generator implementation is solid:

  • Clear helper functions for macro generation
  • Proper error handling with exceptions and logging
  • Well-documented macro dependencies (INITIALIZE_SITES before INITIALIZE_COUPLINGMAP)
  • Correct use of value returns instead of const references
  • All past review issues have been addressed
include/mqt-core/qdmi/sc/Device.hpp (1)

1-305: LGTM!

The Device header demonstrates good design:

  • Thread-safe singleton pattern with proper lifecycle management
  • Session status tracking for state validation
  • All includes are self-contained
  • Out-of-line destructor for proper unique_ptr usage
  • Job methods correctly declared as instance methods
  • Factory patterns for Site and Operation creation
  • Clear separation between Device, Session, Job, Site, and Operation concerns

All previously identified issues have been resolved.

src/qdmi/sc/Device.cpp (1)

1-501: LGTM!

The Device implementation is well-structured and correct:

  • Thread-safe singleton: Proper use of atomic operations with compare_exchange_strong for initialization
  • Lifecycle enforcement: Sessions must be INITIALIZED before creating jobs, preventing misuse
  • Argument validation: All C API entry points validate handles and parameters before delegating
  • Minimal device semantics: Job operations correctly return NOTSUPPORTED while maintaining API completeness
  • Property queries: Well-implemented using macros for consistency (ADD_STRING_PROPERTY, ADD_SINGLE_VALUE_PROPERTY, ADD_LIST_PROPERTY)
  • STRNCPY safety: Correctly uses (size-1) to avoid buffer overruns on both Windows and POSIX

The acknowledged lack of concurrency protection for sessions_/jobs_ maps is acceptable for the current single-threaded usage and documented for future work.

All past review concerns have been addressed.

Copy link
Member

@burgholzer burgholzer left a comment

Choose a reason for hiding this comment

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

Two last points before getting this in.

Copy link
Member

@burgholzer burgholzer left a comment

Choose a reason for hiding this comment

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

I am happy once CI is happy here. Thanks for your work @ystade!
Edit: CI does not really seem happy yet.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

♻️ Duplicate comments (1)
json/sc/device.json (1)

186-189: Align r gate numParameters with Qiskit RGate (2 parameters, not 3).

The "r" operation is configured with "numParameters": 3, but the corresponding Qiskit RGate only takes two parameters (theta, phi). Keeping this at 3 will misrepresent the gate in QDMI metadata and likely confuse or break Qiskit-side tooling that expects the standard 2‑parameter R gate.

Unless you intentionally model a different 3‑parameter gate here, please change this to 2 (or rename the operation if it should remain 3‑parameter):

-  "operations": [
-    { "name": "r", "numParameters": 3, "numQubits": 1 },
-    { "name": "cz", "numParameters": 0, "numQubits": 2 }
-  ]
+  "operations": [
+    { "name": "r", "numParameters": 2, "numQubits": 1 },
+    { "name": "cz", "numParameters": 0, "numQubits": 2 }
+  ]
According to the latest Qiskit documentation, how many parameters does qiskit.circuit.library.RGate take, and what are they called?
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bcf7f87 and 724e825.

📒 Files selected for processing (4)
  • include/mqt-core/qdmi/sc/Device.hpp (1 hunks)
  • json/sc/device.json (1 hunks)
  • src/qdmi/sc/Device.cpp (1 hunks)
  • src/qdmi/sc/Generator.cpp (1 hunks)
🧰 Additional context used
🧠 Learnings (8)
📓 Common learnings
Learnt from: marcelwa
Repo: munich-quantum-toolkit/core PR: 1243
File: test/python/qdmi/qiskit/test_qdmi_qiskit_backend.py:0-0
Timestamp: 2025-11-04T14:28:32.371Z
Learning: In the munich-quantum-toolkit/core repository, at least one FoMaC device is always available during testing, so skip logic for missing devices in QDMI Qiskit backend tests is not necessary.
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.
Learnt from: marcelwa
Repo: munich-quantum-toolkit/core PR: 1243
File: test/python/qdmi/qiskit/test_qdmi_qiskit_site_handling.py:162-173
Timestamp: 2025-10-17T11:09:50.147Z
Learning: For QDMI tests that reference a specific named device via fixture (e.g., "MQT NA Default QDMI Device"), it is acceptable to hard-code device-specific values such as zone counts and indices, as these tests are intentionally coupled to that device's structure and serve as structural invariant checks.
📚 Learning: 2025-11-01T15:57:31.153Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1283
File: src/qir/runtime/QIR.cpp:196-201
Timestamp: 2025-11-01T15:57:31.153Z
Learning: In the QIR runtime (src/qir/runtime/QIR.cpp), the PRX gate (__quantum__qis__prx__body) is an alias for the R gate (Phased X-Rotation) and should call runtime.apply<qc::R>(theta, phi, qubit), not runtime.apply<qc::RX>() which is a single-parameter rotation gate.

Applied to files:

  • json/sc/device.json
📚 Learning: 2025-10-17T11:09:50.147Z
Learnt from: marcelwa
Repo: munich-quantum-toolkit/core PR: 1243
File: test/python/qdmi/qiskit/test_qdmi_qiskit_site_handling.py:162-173
Timestamp: 2025-10-17T11:09:50.147Z
Learning: For QDMI tests that reference a specific named device via fixture (e.g., "MQT NA Default QDMI Device"), it is acceptable to hard-code device-specific values such as zone counts and indices, as these tests are intentionally coupled to that device's structure and serve as structural invariant checks.

Applied to files:

  • json/sc/device.json
  • src/qdmi/sc/Device.cpp
  • include/mqt-core/qdmi/sc/Device.hpp
📚 Learning: 2025-11-04T14:28:32.371Z
Learnt from: marcelwa
Repo: munich-quantum-toolkit/core PR: 1243
File: test/python/qdmi/qiskit/test_qdmi_qiskit_backend.py:0-0
Timestamp: 2025-11-04T14:28:32.371Z
Learning: In the munich-quantum-toolkit/core repository, at least one FoMaC device is always available during testing, so skip logic for missing devices in QDMI Qiskit backend tests is not necessary.

Applied to files:

  • json/sc/device.json
  • src/qdmi/sc/Device.cpp
  • include/mqt-core/qdmi/sc/Device.hpp
📚 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:

  • src/qdmi/sc/Generator.cpp
  • src/qdmi/sc/Device.cpp
  • include/mqt-core/qdmi/sc/Device.hpp
📚 Learning: 2025-11-05T07:42:45.507Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1287
File: test/qdmi/dd/error_handling_test.cpp:118-194
Timestamp: 2025-11-05T07:42:45.507Z
Learning: In the munich-quantum-toolkit/core QDMI device API, session parameters can only be set before calling `device_session_init()`. Once a session is initialized, any attempt to set a parameter returns `QDMI_ERROR_BADSTATE`. Since `SessionGuard` (in test/qdmi/dd/helpers/test_utils.hpp) automatically initializes the session in its constructor, tests that need to verify session parameter setting behavior before initialization must allocate a separate uninitialized session rather than reusing the `SessionGuard`'s session.

Applied to files:

  • src/qdmi/sc/Device.cpp
  • include/mqt-core/qdmi/sc/Device.hpp
📚 Learning: 2025-11-04T19:50:14.489Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1287
File: test/qdmi/dd/helpers/test_utils.cpp:103-118
Timestamp: 2025-11-04T19:50:14.489Z
Learning: In the munich-quantum-toolkit/core QDMI device tests, when QDMI APIs return a string result size `ks` that includes a null terminator, the pattern `std::string keys(ks - 1, '\0'); ... device_job_get_results(..., ks, keys.data(), nullptr)` is correct and safe. The string allocates `ks` bytes total (ks-1 content + implicit null), and the API writing `ks` bytes (including trailing null) fits exactly into this space without buffer overrun.

Applied to files:

  • src/qdmi/sc/Device.cpp
📚 Learning: 2025-10-07T15:30:42.946Z
Learnt from: MatthiasReumann
Repo: munich-quantum-toolkit/core PR: 1237
File: mlir/include/mlir/Dialect/MQTOpt/Transforms/Transpilation/Layout.h:219-231
Timestamp: 2025-10-07T15:30:42.946Z
Learning: In the Layout class for MLIR quantum routing (mlir/include/mlir/Dialect/MQTOpt/Transforms/Transpilation/Layout.h), the swap method intentionally does NOT swap the hw fields in QubitInfo. This is correct because SSA values represent quantum states at fixed hardware locations, and only their program index associations change during a SWAP gate. The hw field indicates where an SSA value physically resides and remains constant.

Applied to files:

  • src/qdmi/sc/Device.cpp
🧬 Code graph analysis (2)
src/qdmi/sc/Generator.cpp (2)
include/mqt-core/qdmi/sc/Generator.hpp (5)
  • device (111-111)
  • device (122-122)
  • os (73-73)
  • path (82-82)
  • path (100-100)
include/mqt-core/qdmi/sc/Device.hpp (1)
  • id (267-268)
include/mqt-core/qdmi/sc/Device.hpp (1)
src/qdmi/sc/Device.cpp (3)
  • Device (101-110)
  • Device (111-114)
  • site (326-326)
🪛 GitHub Check: 🇨‌ Lint / 🚨 Lint
src/qdmi/sc/Device.cpp

[warning] 366-366: src/qdmi/sc/Device.cpp:366:62 [cppcoreguidelines-use-default-member-init]
member initializer for 'numQubits_' is redundant


[warning] 109-109: src/qdmi/sc/Device.cpp:109:3 [bugprone-use-after-move]
'_couplings' used after it was moved


[warning] 99-99: src/qdmi/sc/Device.cpp:99:6 [misc-include-cleaner]
no header providing "std::atomic" is directly included

⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: 🐍 Test (windows-2022) / 🐍 windows-2022
  • GitHub Check: 🐍 Test (macos-15-intel) / 🐍 macos-15-intel
  • GitHub Check: 🐍 Test (ubuntu-24.04) / 🐍 ubuntu-24.04
  • GitHub Check: 🇨‌ Test 🍎 (macos-14, clang, Debug) / 🍎 macos-14 clang Debug
🔇 Additional comments (1)
src/qdmi/sc/Device.cpp (1)

525-525: Guard MQT_SC_QDMI_device_job_free against null job handles.

Unlike the other C wrappers, MQT_SC_QDMI_device_job_free dereferences job unconditionally. A bad caller passing nullptr will segfault here, while sessionFree and all job accessors defensively validate their handles.

Given the function returns void, treating a null job as a no-op is consistent with how sessionFree behaves:

-void MQT_SC_QDMI_device_job_free(MQT_SC_QDMI_Device_Job job) { job->free(); }
+void MQT_SC_QDMI_device_job_free(MQT_SC_QDMI_Device_Job job) {
+  if (job == nullptr) {
+    return;
+  }
+  job->free();
+}

This removes a potential crash point without affecting valid callers.

Signed-off-by: burgholzer <burgholzer@me.com>
Signed-off-by: burgholzer <burgholzer@me.com>
Signed-off-by: burgholzer <burgholzer@me.com>
Signed-off-by: burgholzer <burgholzer@me.com>
Signed-off-by: burgholzer <burgholzer@me.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

♻️ Duplicate comments (2)
src/qdmi/sc/Device.cpp (2)

364-369: Optional: redundant numQubits_(1) initialization.

The single-qubit constructor explicitly initializes numQubits_(1) even though the member has a default initializer of 1 in the class definition, triggering a cppcoreguidelines-use-default-member-init lint warning. You can drop numQubits_(1) from the initializer list here to rely on the default, though keeping it may provide symmetry with the two-qubit constructor (line 374) where numQubits_(2) is necessary.

If you prefer to silence the lint:

 MQT_SC_QDMI_Operation_impl_d::MQT_SC_QDMI_Operation_impl_d(
     std::string name, const size_t numParameters,
     const std::vector<MQT_SC_QDMI_Site>& sites)
-    : name_(std::move(name)), numParameters_(numParameters), numQubits_(1),
+    : name_(std::move(name)), numParameters_(numParameters),
       supportedSites_(sites) {

526-526: Add null check to MQT_SC_QDMI_device_job_free for consistency and safety.

All other C API entry points validate their handle arguments before dereferencing (e.g., lines 499, 531, 541, 548, etc.), but device_job_free directly calls job->free() without checking if job is null. While well-behaved callers should never pass null, adding a guard improves robustness and consistency with the rest of the API surface.

Apply this diff to add the null check:

-void MQT_SC_QDMI_device_job_free(MQT_SC_QDMI_Device_Job job) { job->free(); }
+void MQT_SC_QDMI_device_job_free(MQT_SC_QDMI_Device_Job job) {
+  if (job != nullptr) {
+    job->free();
+  }
+}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 69f2816 and ed694b8.

📒 Files selected for processing (2)
  • src/qdmi/sc/Device.cpp (1 hunks)
  • src/qdmi/sc/Generator.cpp (1 hunks)
🧰 Additional context used
🧠 Learnings (9)
📓 Common learnings
Learnt from: marcelwa
Repo: munich-quantum-toolkit/core PR: 1243
File: test/python/qdmi/qiskit/test_qdmi_qiskit_backend.py:0-0
Timestamp: 2025-11-04T14:28:32.371Z
Learning: In the munich-quantum-toolkit/core repository, at least one FoMaC device is always available during testing, so skip logic for missing devices in QDMI Qiskit backend tests is not necessary.
📚 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:

  • src/qdmi/sc/Generator.cpp
  • src/qdmi/sc/Device.cpp
📚 Learning: 2025-11-05T07:42:45.507Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1287
File: test/qdmi/dd/error_handling_test.cpp:118-194
Timestamp: 2025-11-05T07:42:45.507Z
Learning: In the munich-quantum-toolkit/core QDMI device API, session parameters can only be set before calling `device_session_init()`. Once a session is initialized, any attempt to set a parameter returns `QDMI_ERROR_BADSTATE`. Since `SessionGuard` (in test/qdmi/dd/helpers/test_utils.hpp) automatically initializes the session in its constructor, tests that need to verify session parameter setting behavior before initialization must allocate a separate uninitialized session rather than reusing the `SessionGuard`'s session.

Applied to files:

  • src/qdmi/sc/Generator.cpp
  • src/qdmi/sc/Device.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:

  • src/qdmi/sc/Generator.cpp
📚 Learning: 2025-10-17T11:09:50.147Z
Learnt from: marcelwa
Repo: munich-quantum-toolkit/core PR: 1243
File: test/python/qdmi/qiskit/test_qdmi_qiskit_site_handling.py:162-173
Timestamp: 2025-10-17T11:09:50.147Z
Learning: For QDMI tests that reference a specific named device via fixture (e.g., "MQT NA Default QDMI Device"), it is acceptable to hard-code device-specific values such as zone counts and indices, as these tests are intentionally coupled to that device's structure and serve as structural invariant checks.

Applied to files:

  • src/qdmi/sc/Device.cpp
📚 Learning: 2025-11-04T19:50:14.489Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1287
File: test/qdmi/dd/helpers/test_utils.cpp:103-118
Timestamp: 2025-11-04T19:50:14.489Z
Learning: In the munich-quantum-toolkit/core QDMI device tests, when QDMI APIs return a string result size `ks` that includes a null terminator, the pattern `std::string keys(ks - 1, '\0'); ... device_job_get_results(..., ks, keys.data(), nullptr)` is correct and safe. The string allocates `ks` bytes total (ks-1 content + implicit null), and the API writing `ks` bytes (including trailing null) fits exactly into this space without buffer overrun.

Applied to files:

  • src/qdmi/sc/Device.cpp
📚 Learning: 2025-11-04T14:28:32.371Z
Learnt from: marcelwa
Repo: munich-quantum-toolkit/core PR: 1243
File: test/python/qdmi/qiskit/test_qdmi_qiskit_backend.py:0-0
Timestamp: 2025-11-04T14:28:32.371Z
Learning: In the munich-quantum-toolkit/core repository, at least one FoMaC device is always available during testing, so skip logic for missing devices in QDMI Qiskit backend tests is not necessary.

Applied to files:

  • src/qdmi/sc/Device.cpp
📚 Learning: 2025-10-07T15:30:42.946Z
Learnt from: MatthiasReumann
Repo: munich-quantum-toolkit/core PR: 1237
File: mlir/include/mlir/Dialect/MQTOpt/Transforms/Transpilation/Layout.h:219-231
Timestamp: 2025-10-07T15:30:42.946Z
Learning: In the Layout class for MLIR quantum routing (mlir/include/mlir/Dialect/MQTOpt/Transforms/Transpilation/Layout.h), the swap method intentionally does NOT swap the hw fields in QubitInfo. This is correct because SSA values represent quantum states at fixed hardware locations, and only their program index associations change during a SWAP gate. The hw field indicates where an SSA value physically resides and remains constant.

Applied to files:

  • src/qdmi/sc/Device.cpp
📚 Learning: 2025-10-09T13:13:51.224Z
Learnt from: DRovara
Repo: munich-quantum-toolkit/core PR: 1108
File: mlir/lib/Dialect/MQTOpt/Transforms/ReplaceBasisStateControlsWithIfPattern.cpp:171-180
Timestamp: 2025-10-09T13:13:51.224Z
Learning: In MQT Core MLIR, UnitaryInterface operations guarantee 1-1 correspondence between input and output qubits in the same order. When cloning or modifying unitary operations (e.g., removing controls), this correspondence is maintained by construction, so yielding getAllInQubits() in else-branches matches the result types from the operation's outputs.

Applied to files:

  • src/qdmi/sc/Device.cpp
🧬 Code graph analysis (1)
src/qdmi/sc/Generator.cpp (3)
include/mqt-core/qdmi/sc/Generator.hpp (6)
  • device (111-111)
  • device (122-122)
  • os (73-73)
  • path (82-82)
  • path (100-100)
  • is (91-91)
include/mqt-core/qdmi/sc/Device.hpp (1)
  • id (267-268)
test/qdmi/sc/test_device.cpp (1)
  • nodiscard (23-41)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: 🐍 Test (ubuntu-24.04) / 🐍 ubuntu-24.04
  • GitHub Check: 🐍 Test (ubuntu-24.04-arm) / 🐍 ubuntu-24.04-arm
  • GitHub Check: 🐍 Test (windows-2022) / 🐍 windows-2022
🔇 Additional comments (2)
src/qdmi/sc/Device.cpp (2)

99-198: LGTM: Device singleton and property query implementation.

The Device singleton lifecycle (lines 116–139) uses proper atomic operations (compare_exchange_strong, exchange) for thread-safe initialization and finalization. Session and job management via std::unique_ptr in maps ensures automatic cleanup, and the explicit sessions_.clear() in the destructor (line 114) prevents use-after-free edge cases. The macro-based property query pattern (lines 158–198) centralizes validation and reduces repetition across device, site, and operation queries.


392-482: LGTM: Operation property query logic handles single- and two-qubit cases correctly.

The queryProperty implementation (lines 392–482) uses std::visit to dispatch on the supportedSites_ variant, validating single-qubit sites via binary_search (line 410) and two-qubit pairs by normalizing and searching (lines 421–432). The reinterpret_cast for two-qubit site flattening (lines 469–472) is safe given the static_assert checks (lines 461–465) confirming standard layout and expected size.

Signed-off-by: burgholzer <burgholzer@me.com>
Signed-off-by: burgholzer <burgholzer@me.com>
…sites into account

Signed-off-by: burgholzer <burgholzer@me.com>
Signed-off-by: burgholzer <burgholzer@me.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ed694b8 and 66b7938.

📒 Files selected for processing (2)
  • src/qdmi/sc/Generator.cpp (1 hunks)
  • test/fomac/test_fomac.cpp (2 hunks)
🧰 Additional context used
🧠 Learnings (9)
📓 Common learnings
Learnt from: marcelwa
Repo: munich-quantum-toolkit/core PR: 1243
File: test/python/qdmi/qiskit/test_qdmi_qiskit_site_handling.py:162-173
Timestamp: 2025-10-17T11:09:50.147Z
Learning: For QDMI tests that reference a specific named device via fixture (e.g., "MQT NA Default QDMI Device"), it is acceptable to hard-code device-specific values such as zone counts and indices, as these tests are intentionally coupled to that device's structure and serve as structural invariant checks.
📚 Learning: 2025-11-26T10:29:36.435Z
Learnt from: marcelwa
Repo: munich-quantum-toolkit/core PR: 1243
File: test/python/fomac/test_fomac.py:54-66
Timestamp: 2025-11-26T10:29:36.435Z
Learning: In test/python/fomac/test_fomac.py, the `ddsim_device` fixture returns `Device | None` even though it only returns a `Device` or calls `pytest.skip()`. The `| None` annotation is required for the type checker to pass, as type checkers may not recognize `pytest.skip()` as a function that never returns.

Applied to files:

  • test/fomac/test_fomac.cpp
📚 Learning: 2025-11-04T14:28:32.371Z
Learnt from: marcelwa
Repo: munich-quantum-toolkit/core PR: 1243
File: test/python/qdmi/qiskit/test_qdmi_qiskit_backend.py:0-0
Timestamp: 2025-11-04T14:28:32.371Z
Learning: In the munich-quantum-toolkit/core repository, at least one FoMaC device is always available during testing, so skip logic for missing devices in QDMI Qiskit backend tests is not necessary.

Applied to files:

  • test/fomac/test_fomac.cpp
📚 Learning: 2025-10-09T13:20:11.483Z
Learnt from: DRovara
Repo: munich-quantum-toolkit/core PR: 1108
File: mlir/test/Dialect/MQTOpt/Transforms/lift-measurements.mlir:269-288
Timestamp: 2025-10-09T13:20:11.483Z
Learning: In the MQT MLIR dialect, the `rz` gate should not be included in the `DIAGONAL_GATES` set for the `ReplaceBasisStateControlsWithIfPattern` because its operator matrix does not have the required shape | 1 0 | / | 0 x | for the targets-as-controls optimization. It is only included in `LiftMeasurementsAboveGatesPatterns` where the matrix structure requirement differs.

Applied to files:

  • test/fomac/test_fomac.cpp
📚 Learning: 2025-11-01T15:57:31.153Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1283
File: src/qir/runtime/QIR.cpp:196-201
Timestamp: 2025-11-01T15:57:31.153Z
Learning: In the QIR runtime (src/qir/runtime/QIR.cpp), the PRX gate (__quantum__qis__prx__body) is an alias for the R gate (Phased X-Rotation) and should call runtime.apply<qc::R>(theta, phi, qubit), not runtime.apply<qc::RX>() which is a single-parameter rotation gate.

Applied to files:

  • test/fomac/test_fomac.cpp
📚 Learning: 2025-10-17T11:09:50.147Z
Learnt from: marcelwa
Repo: munich-quantum-toolkit/core PR: 1243
File: test/python/qdmi/qiskit/test_qdmi_qiskit_site_handling.py:162-173
Timestamp: 2025-10-17T11:09:50.147Z
Learning: For QDMI tests that reference a specific named device via fixture (e.g., "MQT NA Default QDMI Device"), it is acceptable to hard-code device-specific values such as zone counts and indices, as these tests are intentionally coupled to that device's structure and serve as structural invariant checks.

Applied to files:

  • test/fomac/test_fomac.cpp
📚 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:

  • src/qdmi/sc/Generator.cpp
📚 Learning: 2025-11-05T07:42:45.507Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1287
File: test/qdmi/dd/error_handling_test.cpp:118-194
Timestamp: 2025-11-05T07:42:45.507Z
Learning: In the munich-quantum-toolkit/core QDMI device API, session parameters can only be set before calling `device_session_init()`. Once a session is initialized, any attempt to set a parameter returns `QDMI_ERROR_BADSTATE`. Since `SessionGuard` (in test/qdmi/dd/helpers/test_utils.hpp) automatically initializes the session in its constructor, tests that need to verify session parameter setting behavior before initialization must allocate a separate uninitialized session rather than reusing the `SessionGuard`'s session.

Applied to files:

  • src/qdmi/sc/Generator.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:

  • src/qdmi/sc/Generator.cpp
🧬 Code graph analysis (1)
src/qdmi/sc/Generator.cpp (2)
include/mqt-core/qdmi/sc/Generator.hpp (6)
  • device (111-111)
  • device (122-122)
  • os (73-73)
  • path (82-82)
  • path (100-100)
  • is (91-91)
include/mqt-core/qdmi/sc/Device.hpp (1)
  • id (267-268)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: 🐍 Test (macos-15-intel) / 🐍 macos-15-intel
  • GitHub Check: 🐍 Test (windows-2022) / 🐍 windows-2022
🔇 Additional comments (12)
src/qdmi/sc/Generator.cpp (9)

1-27: LGTM!

File header and includes are clean. The file description correctly refers to superconducting devices (past issue resolved), and the includes are minimal and necessary.


28-62: LGTM!

The helper functions populateArrayFields, writeName, and writeQubitsNum are straightforward and correctly generate initialization macros. The populateArrayFields function ensures the JSON schema template has example entries.


76-98: LGTM with a dependency note.

The writeSites function correctly generates the site and coupling initialization logic. The _singleQubitSites and _couplings vectors created here are properly used by subsequent macros (see documentation at lines 138-140).


100-130: LGTM!

The writeOperations function correctly generates operation initialization code for single- and two-qubit operations. The design choice to support only 1- and 2-qubit operations is reasonable for SC devices, with appropriate error handling for unsupported operation counts.


132-146: LGTM!

The writeCouplingMap function and its documentation correctly describe the copy semantics and dependency on the _couplings variable created by INITIALIZE_SITES. Past documentation issue has been properly resolved.


149-185: LGTM!

Both writeJSONSchema overloads are well-implemented with proper error handling and file management. The NOLINTNEXTLINE suppression for misc-include-cleaner at line 157 is appropriate for nlohmann::json's template metaprogramming.


187-229: LGTM!

Both readJSON overloads are correctly implemented with proper value semantics (line 226 correctly returns by value, past issue resolved) and comprehensive error handling for file I/O and JSON parsing.


256-276: LGTM!

The writeHeader file overload is well-implemented with proper error handling and logging.


83-88: Consider using std::transform for C++17 compatibility.

The generated code uses std::ranges::transform (a C++20 feature). For broader compatibility, consider using std::transform from <algorithm> instead, which works in C++17 and later:

-os << ";\\\n  std::ranges::transform(var, "
-      "std::back_inserter(_singleQubitSites), [](const "
-      "std::unique_ptr<MQT_SC_QDMI_Site_impl_d>& site) { return site.get(); "
-      "})";
+os << ";\\\n  std::transform(var.begin(), var.end(), "
+      "std::back_inserter(_singleQubitSites), [](const auto& site) { "
+      "return site.get(); })";

This would eliminate the need for #include <ranges> in the generated header and maintain compatibility with C++17 compilers.

⛔ Skipped due to learnings
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.
test/fomac/test_fomac.cpp (3)

34-41: Vector-based site/operation storage in test fixtures looks sound

Switching SiteTest and OperationTest to store full std::vector<...> and populating them in SetUp() via device.getSites() / getOperations() with ASSERT_FALSE(...empty()) is correct and removes the previous pointer lifetime issues. It also makes iterating over all sites/operations straightforward and safe.

Also applies to: 44-51


349-365: Operation name/qubits/parameters tests correctly generalized to all operations

Iterating over operations and checking getName(), getQubitsNum(), and getParametersNum() per operation is correct and aligns with the new vector-based fixture. The EXPECT_NO_THROW(EXPECT_FALSE(operation.getName().empty())); pattern is consistent with existing tests and no longer has the stray semicolon issue mentioned in earlier reviews.


469-491: The SitePairs test correctly enforces QDMI specification invariants—no action needed.

The hard-coded invariants are not arbitrary device-level rules. The getSitePairs() method is explicitly documented as interpreting sites "according to the QDMI specification" and the implementation enforces that specification-level contract:

  • getSitePairs() returns nullopt for non-2-qubit operations, zoned operations, or operations with invalid site data
  • For valid 2-qubit operations, it pairs consecutive sites in the returned list

These are QDMI specification requirements, not device-specific assumptions. Future devices cannot deviate from these invariants without violating the QDMI specification itself. The test correctly verifies specification compliance across all devices.

Signed-off-by: burgholzer <burgholzer@me.com>
Signed-off-by: burgholzer <burgholzer@me.com>
@burgholzer burgholzer merged commit 03456fc into main Dec 4, 2025
34 checks passed
@burgholzer burgholzer deleted the ystade/qdmi-sc-device branch December 4, 2025 23:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c++ Anything related to C++ code enhancement New feature or request QDMI Anything related to QDMI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants