✨ Build target environments from QDMI payloads - #2227
Conversation
000f1a7 to
119e8dd
Compare
119e8dd to
5aefae1
Compare
5aefae1 to
f6ccb12
Compare
c463a53 to
4289979
Compare
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
fcf7027 to
0c598df
Compare
Snapshot one exact device-supported descriptor, its grouped optional features, and its normative baseline into an owning TargetEnvironment. Expose matching C++ and Python factories. Assisted-by: GPT-5.6 Sol via Codex
Exercise constrained and malformed feature groups, invalid descriptors, snapshot propagation, and exception containment through the public adapter entry points. Remove duplicate validation branches that cannot run after the QDMI C++ client validates provider records and encodings. Assisted-by: GPT-5.6 Sol via Codex
0c598df to
6d85e61
Compare
burgholzer
left a comment
There was a problem hiding this comment.
This largely looks good to me. I one simplification request, one lifted constraint and likely some better bindings. I have the feeling that changes in the lower layers of the PR stack will trigger a few more changes here.
I am also wondering whether there is a bit too much overlap/duplication between the MLIR and the QDMI concepts and whether some of that could be simplified while still maintaining the proper separation between the two.
@denialhaag @simon1hofmann same question here as in the other PRs: Do you also see some things that need changes?
| /** | ||
| * @brief Snapshot a QDMI device and one accepted payload as a target | ||
| * environment. | ||
| * | ||
| * @details The adapter preserves the exact program format, groups feature | ||
| * records with the same ID and value, and adds the normative baseline of a | ||
| * standard payload. Unknown optional feature metadata remains unknown. | ||
| */ | ||
| [[nodiscard]] llvm::Expected<TargetEnvironment> | ||
| targetEnvironmentFromDevice(const qdmi::Device& device, | ||
| const QDMI_Program_Format& format); | ||
|
|
||
| /** | ||
| * @brief Open a registered QDMI device and snapshot one accepted payload. | ||
| * | ||
| * @details This adapter contains exceptions from the QDMI C++ API and returns | ||
| * them as LLVM errors. The returned environment owns all queried metadata. | ||
| */ | ||
| [[nodiscard]] llvm::Expected<TargetEnvironment> | ||
| targetEnvironmentFromDeviceId(std::string_view deviceId, | ||
| const QDMI_Program_Format& format); | ||
|
|
There was a problem hiding this comment.
This is just me trying to be pragmatic: Most devices will expose a single payload format that they support. In these cases, it would be quite convenient to define a shortcut that either just uses the device or the ID without an explicit program format in the call.
The only thing to choose would be what to do with devices that offer multiple formats. One plausible option would be to default to the first supported format, which, by definition, is the preferred format by the device.
It should likely be pointed out explicitly that there is an overload for the convenience shortcut that allows specifying an explicit format.
As a follow-up, all code that does not explicitly need it otherwise and all docs may be moved to the convenience function.
| if (format.id != "qir" || format.version != "2.1.0" || | ||
| format.profile != "adaptive") { | ||
| return {}; | ||
| } |
There was a problem hiding this comment.
The 2.1.0 feels a bit more restrictive than this likely needs to be.
|
|
||
| import qiskit.circuit | ||
|
|
||
| import mqt.core.qdmi |
There was a problem hiding this comment.
This line feels odd and I am pretty sure that we can get rid of that by better writing the bindings.
simon1hofmann
left a comment
There was a problem hiding this comment.
Only have a couple of comments about the docs, but besides that this PR also looks really good!
| return copyValue(DEVICE_NAME.data(), DEVICE_NAME.size() + 1U, size, value, | ||
| sizeRet); | ||
| } | ||
| case QDMI_DEVICE_PROPERTY_QUBITSNUM: { |
There was a problem hiding this comment.
Was this the reason for calling it qubits_num in the other PR?
There was a problem hiding this comment.
Yeah. Mainly. But we use the other wording practically everywhere else. So I would be fine with the syntactic break going from C to C++.
| metadata are unknown unless the caller states them: | ||
|
|
||
| ```python | ||
| target = CompilerTarget( |
There was a problem hiding this comment.
CompilerTarget is not imported anymore (deleted in line 18).
There was a problem hiding this comment.
Ah. We need to be careful here while the docs in CI are failing. They should still all pass locally for all of the changes here and produce correct output.
| environment = TargetEnvironment(target, payload) | ||
| environment = TargetEnvironment.from_device_id( | ||
| "mqt.sc.iqm.garnet", | ||
| ProgramFormat.QIR21_BASE_BINARY, |
There was a problem hiding this comment.
The SC provider does not advertise any program formats right?
Same for the example in lines 111-112.
There was a problem hiding this comment.
It does not. But maybe it should.
Maybe the configuration for the device should include which formats the device claims to accept/support. Would allow a more faithful model of an IQM machine.
denialhaag
left a comment
There was a problem hiding this comment.
This also LGTM! 🙂 I just have one nitpick and a comment on the documentation:
| #include <nanobind/stl/string_view.h> // NOLINT(misc-include-cleaner) | ||
| #include <nanobind/stl/variant.h> // NOLINT(misc-include-cleaner) | ||
| #include <nanobind/stl/vector.h> // NOLINT(misc-include-cleaner) | ||
| #include <qdmi/constants.h> |
There was a problem hiding this comment.
We still need to streamline our includes when we have fewer PRs open, but this would comply with the current style:
| #include <qdmi/constants.h> | |
| #include "qdmi/constants.h" |
There was a problem hiding this comment.
Yeah. You are right. Still have this wired wrongly in my brain. We did device at some point to only treat stdlib includes with angle brackets, right?
Because this is still an external header pulled in as a dependency.
There was a problem hiding this comment.
Yeah, but then we changed our minds again, following the discussion in FullStaQD/qcc#37. I still have it on my list to apply this across the MQT. Maybe just before the v4 release is a good time, since we hopefully won't have too many open PRs at that point. 🤔
There was a problem hiding this comment.
Yeah. Before the release makes sense.
We may even want to consider that as a point where we may use an "mqt" namespace for our code to differentiate it a tad bit more from plain mlir. Similar to how this is done in FullStaQD with qcc. I was initially opposed to that but I am starting to see the potential benefits.
| The payload specification identifies the exact representation selected for the | ||
| device. MQT Core derives the compiler output from that specification and uses | ||
| The QDMI adapter checks that the device accepts the exact program format. It | ||
| groups program-feature records by ID and value, adds the selected format's | ||
| normative baseline, and preserves whether the optional feature list is known. | ||
| MQT Core derives the compiler output from this payload specification and uses | ||
| the canonical QCO pipeline. The targeted overload therefore accepts one | ||
| `TargetEnvironment` and no independent output or custom pipeline. MQT Core's | ||
| QDMI adapter does not yet translate QDMI program-format and feature metadata, so | ||
| callers must construct the payload specification from the device documentation. | ||
|
|
||
| The example has no reported execution capabilities. A producer must add every | ||
| effective capability, including the selected format's baseline. Set | ||
| `optional_capabilities_known=True` only when the producer also knows that the | ||
| list contains every optional device capability. | ||
| `TargetEnvironment` and no independent output or custom pipeline. |
There was a problem hiding this comment.
This might just be me, but this feels overly technical and not user-facing. Again, this might just be me, but my brain switched off while I was reading. 🤠
There was a problem hiding this comment.
This entire page needs a revamp once the implementation is consolidated.
And some of the terminology might still need bike shedding. As pointed out in several of my own review comments, I am not quite happy yet with how some of the things are framed.
🤖 AI text below 🤖
Description
Build one owning compiler
TargetEnvironmentfrom an exact payload accepted by a QDMI device.This pull request:
TargetEnvironment.from_deviceandfrom_device_idPython factories.This PR is stacked on #2226, which supplies the low-level QDMI 1.4 payload contract. Together they complete the QDMI integration requested during review of #2219.
Validation on the complete stack:
AI assistance: OpenAI Codex assisted with implementation, review, testing, and this description.
Checklist
If PR contains AI-assisted content:
🤖 *AI text below* 🤖(titles are exempt).