Skip to content

Commit 1f548e8

Browse files
mergify[bot]burgholzerdenialhaag
authored
🚸 Improve QDMI Integration (backport #1694) (#1698)
## Description This PR originally only aimed to address #1352. However, working on it prompted several follow-ups and improvements for the QDMI support layer as well as a couple of bugfixes. The main change here is still that all QDMI devices are now built as shared libraries by default and that the respective dynamic wrappers have been removed. The QDMI Qiskit wrapper now supports multi-controlled gates as exposed by the DDSIM device. The QDMI Python tests have been significantly streamlined, and a lot of the mocking code is replaced with actual device executions. I will leave this in draft until CI is green because I expect Windows to cause some problems. Edit: As expected, Windows is acting up big again. Edit2: I think I have a working version now. Only took 10h 🫠 Fixes #1352 ## Checklist - [x] The pull request only contains commits that are focused and relevant to this change. - [x] I have added appropriate tests that cover the new/changed functionality. - [x] I have updated the documentation to reflect these changes. - [x] I have added entries to the changelog for any noteworthy additions, changes, fixes, or removals. - [x] I have added migration instructions to the upgrade guide (if needed). - [x] The changes follow the project's style guidelines and introduce no new warnings. - [x] The changes are fully tested and pass the CI checks. - [x] I have reviewed my own code changes. **If PR contains AI-assisted content:** - [x] I have disclosed the use of AI tools in the PR description as per our [AI Usage Guidelines](https://github.com/munich-quantum-toolkit/core/blob/main/docs/ai_usage.md). - [x] AI-assisted commits include an `Assisted-by: [Model Name] via [Tool Name]` footer. - [x] I confirm that I have personally reviewed and understood all AI-generated content, and accept full responsibility for it. (cherry picked from commit 4fe097c) --------- Co-authored-by: Lukas Burgholzer <burgholzer@me.com> Co-authored-by: Daniel Haag <121057143+denialhaag@users.noreply.github.com>
1 parent 6c9e16e commit 1f548e8

34 files changed

Lines changed: 1405 additions & 2044 deletions

CHANGELOG.md

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,28 @@ This project adheres to [Semantic Versioning], with the exception that minor rel
99

1010
## [Unreleased]
1111

12+
### Added
13+
14+
- 🚸 Add a measurement instruction to the default SC QDMI device ([#1694]) ([**@burgholzer**])
15+
- ✨ Add support for multi-controlled gates to the QDMI Qiskit backend converter ([#1694]) ([**@burgholzer**])
16+
17+
### Changed
18+
19+
- ♻️ Build all built-in QDMI devices as shared libraries ([#1694]) ([**@burgholzer**])
20+
- ⬆️ Update minimum supported Qiskit version to 1.1.0 ([#1694]) ([**@burgholzer**])
21+
22+
### Fixed
23+
24+
- 🐛 Fix segfault in DD `sample` method when idle classical bits are present ([#1694]) ([**@burgholzer**])
25+
26+
### Removed
27+
28+
- 🔥 Remove shared library wrappers for QDMI devices ([#1694]) ([**@burgholzer**])
29+
1230
## [3.5.1] - 2026-04-23
1331

32+
_If you are upgrading: please see [`UPGRADING.md`](UPGRADING.md#351)._
33+
1434
### Fixed
1535

1636
- 🐛 Fix malformed include directories in exported `nlohmann_json` CMake targets for component-based installs ([#1662]) ([**@burgholzer**])
@@ -21,7 +41,7 @@ _If you are upgrading: please see [`UPGRADING.md`](UPGRADING.md#350)._
2141

2242
### Added
2343

24-
- ✨ Add support for multi-controlled gates to ZX package ([#1380]) ([**@keefehuang**])
44+
- ✨ Add support for multi-controlled gates to ZX package ([#1380]) ([**@keefehuang**], [**@denialhaag**])
2545
- ✨ Add Sampler and Estimator primitives to the QDMI-Qiskit interface ([#1507]) ([**@marcelwa**])
2646

2747
### Changed
@@ -342,6 +362,7 @@ _📚 Refer to the [GitHub Release Notes](https://github.com/munich-quantum-tool
342362

343363
<!-- PR links -->
344364

365+
[#1694]: https://github.com/munich-quantum-toolkit/core/pull/1694
345366
[#1662]: https://github.com/munich-quantum-toolkit/core/pull/1662
346367
[#1654]: https://github.com/munich-quantum-toolkit/core/pull/1654
347368
[#1652]: https://github.com/munich-quantum-toolkit/core/pull/1652

UPGRADING.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,33 @@ This document describes breaking changes and how to upgrade. For a complete list
44

55
## [Unreleased]
66

7+
### Changes to builtin QDMI devices
8+
9+
The builtin QDMI devices (with prefixes `MQT_SC`, `MQT_NA`, and `MQT_DDSIM`) are now all built as shared libraries by default.
10+
In turn, the shared library wrappers (with prefixes `MQT_SC_DYN` and `MQT_NA_DYN`) have been removed entirely.
11+
MQT Core's QDMI driver will automatically load the shared libraries of the builtin devices if they are available in the library search path.
12+
If you were previously using the statically builtin devices, no changes should be necessary as the shared libraries are now the default.
13+
If you were previously using the shared library wrappers, you should switch to using the builtin devices instead, which are now shared libraries by default.
14+
15+
### Broader operation support in QDMI Qiskit converter
16+
17+
The QDMI Qiskit converter now supports a broader range of operations, including multi-controlled gates such as `mcx`, `mcz`, `mcrx`, and more.
18+
As a consequence, these operations can now be directly used without requiring decomposition, for example, with the builtin `DDSIM` QDMI device.
19+
20+
### Minimum supported Qiskit version
21+
22+
From this release onwards, MQT Core requires Qiskit version 1.1.0 or higher.
23+
This is due to the fact that we are relying on some fixes to Qiskit primitives that were introduced in that version.
24+
If you are using MQT Core with Qiskit, please ensure that you have updated to Qiskit 1.1.0 or higher to avoid any compatibility issues.
25+
726
## [3.5.1]
827

928
No breaking changes.
1029

1130
### Component-based CMake installs
1231

1332
Fixed exported `nlohmann_json` CMake metadata so `find_package(mqt-core CONFIG)` no longer propagates an invalid `.../COMPONENT` include directory in component-based installations.
14-
Anyone relying on an installed version of `mqt-core` shall update from `3.5.0` to `3.5.1`.
33+
Anyone relying on an installed version of `mqt-core` should update from 3.5.0 to 3.5.1.
1534

1635
## [3.5.0]
1736

cmake/AddMQTCoreLibrary.cmake

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,14 @@ function(kebab_to_camel output input)
2121
endfunction()
2222

2323
function(add_mqt_core_library name)
24-
cmake_parse_arguments(ARG "" "ALIAS_NAME" "" ${ARGN})
25-
if(BUILD_MQT_CORE_SHARED_LIBS)
24+
cmake_parse_arguments(ARG "FORCE_SHARED;HIDDEN_VISIBILITY" "ALIAS_NAME" "" ${ARGN})
25+
26+
if(ARG_FORCE_SHARED OR BUILD_MQT_CORE_SHARED_LIBS)
2627
add_library(${name} SHARED ${ARG_UNPARSED_ARGUMENTS})
2728
else()
2829
add_library(${name} ${ARG_UNPARSED_ARGUMENTS})
2930
endif()
31+
3032
if(NOT ARG_ALIAS_NAME)
3133
# remove prefix 'mqt-' from target name if exists
3234
string(REGEX REPLACE "^${MQT_CORE_TARGET_NAME}" "" ALIAS_NAME_ARG ${name})
@@ -41,6 +43,14 @@ function(add_mqt_core_library name)
4143
# Add link libraries for warnings and options
4244
target_link_libraries(${name} PRIVATE MQT::ProjectWarnings MQT::ProjectOptions)
4345

46+
if(ARG_HIDDEN_VISIBILITY)
47+
set_target_properties(
48+
${name}
49+
PROPERTIES C_VISIBILITY_PRESET hidden
50+
CXX_VISIBILITY_PRESET hidden
51+
VISIBILITY_INLINES_HIDDEN 1)
52+
endif()
53+
4454
# Set versioning information
4555
set_target_properties(
4656
${name}

cmake/PackageAddTest.cmake

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ macro(PACKAGE_ADD_TEST testname linklibs)
1111
if(NOT TARGET ${testname})
1212
# create an executable in which the tests will be stored
1313
add_executable(${testname} ${ARGN})
14+
# Ensure test executables remain runnable from the build tree during GoogleTest discovery
15+
set_property(TARGET ${testname} PROPERTY BUILD_WITH_INSTALL_RPATH FALSE)
1416
# link the Google test infrastructure and a default main function to the test executable.
1517
target_link_libraries(${testname} PRIVATE ${linklibs} GTest::gmock GTest::gtest_main
1618
MQT::ProjectOptions MQT::ProjectWarnings)
@@ -30,6 +32,8 @@ macro(PACKAGE_ADD_TEST_WITH_WORKING_DIR testname linklibs test_working_directory
3032
if(NOT TARGET ${testname})
3133
# create an executable in which the tests will be stored
3234
add_executable(${testname} ${ARGN})
35+
# Ensure test executables remain runnable from the build tree during GoogleTest discovery
36+
set_property(TARGET ${testname} PROPERTY BUILD_WITH_INSTALL_RPATH FALSE)
3337
# link the Google test infrastructure and a default main function to the test executable.
3438
target_link_libraries(${testname} PRIVATE ${linklibs} GTest::gmock GTest::gtest_main
3539
MQT::ProjectOptions MQT::ProjectWarnings)

docs/qdmi/driver.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ mystnb:
1010

1111
## Objective
1212

13-
A QDMI Driver manages the communication between QDMI devices, such as [MQT Core's NA QDMI Device](na_device.md), and QDMI clients, see the [QDMI specification](https://munich-quantum-software-stack.github.io/QDMI/).
13+
A QDMI Driver manages the communication between QDMI devices, such as [MQT Core's NA QDMI Device](na_device.md) or [MQT Core's DDSIM QDMI Device](ddsim_device.md), and QDMI clients, see the [QDMI specification](https://munich-quantum-software-stack.github.io/QDMI/).
1414
It is responsible for loading the device, forwarding requests from the client to the device, and sending back the results.
15-
The MQT Core's QDMI Driver, {cpp:class}`qdmi::Driver`, comes with the [MQT Core's NA QDMI Device](na_device.md) that is already statically linked into the driver and can directly be used.
15+
MQT Core's QDMI Driver, {cpp:class}`qdmi::Driver`, comes with several preloaded devices that can be used directly.
1616
Other devices can be loaded dynamically at runtime via {cpp:func}`qdmi::Driver::addDynamicDeviceLibrary`.
1717

1818
## Python Bindings
@@ -38,4 +38,5 @@ available_devices = session.get_devices()
3838
# Print the name of every device
3939
for device in available_devices:
4040
print(device.name())
41+
4142
```

include/mqt-core/qdmi/driver/Driver.hpp

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -146,22 +146,6 @@ class DynamicDeviceLibrary final : public DeviceLibrary {
146146
~DynamicDeviceLibrary() override;
147147
};
148148

149-
// Macro to define a static library class that inherits from DeviceLibrary.
150-
// It binds all device library functions to the functions of the static library.
151-
// @param prefix is the prefix used for the function names in the library.
152-
#define DECLARE_STATIC_LIBRARY(prefix) \
153-
class prefix##DeviceLibrary final : public DeviceLibrary { \
154-
public: \
155-
prefix##DeviceLibrary(); \
156-
\
157-
~prefix##DeviceLibrary() override; \
158-
};
159-
160-
// Call the above macro for all static libraries that we want to support.
161-
DECLARE_STATIC_LIBRARY(MQT_NA)
162-
DECLARE_STATIC_LIBRARY(MQT_DDSIM)
163-
DECLARE_STATIC_LIBRARY(MQT_SC)
164-
165149
/**
166150
* @brief The status of a session.
167151
* @details This enum defines the possible states of a session in the QDMI
@@ -178,9 +162,6 @@ enum class SessionStatus : uint8_t {
178162
*/
179163
struct QDMI_Device_impl_d {
180164
private:
181-
// Since we treat this struct as a class, we apply also the naming scheme for
182-
// classes, i.e., an underscore at the end of member names.
183-
184165
/**
185166
* @brief The device library that provides the device interface functions.
186167
* @note This must be a pointer type as we need access to dynamic and static
@@ -265,9 +246,6 @@ struct QDMI_Device_impl_d {
265246
*/
266247
struct QDMI_Job_impl_d {
267248
private:
268-
// Since we treat this struct as a class, we apply also the naming scheme for
269-
// classes, i.e., an underscore at the end of member names.
270-
271249
/// @brief The device job handle.
272250
QDMI_Device_Job deviceJob_ = nullptr;
273251
/// @brief The device associated with the job.
@@ -350,8 +328,6 @@ struct QDMI_Job_impl_d {
350328
/**
351329
* @brief Definition of the QDMI Session.
352330
*/
353-
// Since we treat this struct as a class, we apply also the naming scheme for
354-
// classes, i.e., an underscore at the end of member names.
355331
struct QDMI_Session_impl_d {
356332
private:
357333
/// @brief The status of the session.

json/sc/device.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@
185185
],
186186
"operations": [
187187
{ "name": "r", "numParameters": 2, "numQubits": 1 },
188-
{ "name": "cz", "numParameters": 0, "numQubits": 2 }
188+
{ "name": "cz", "numParameters": 0, "numQubits": 2 },
189+
{ "name": "measure", "numParameters": 0, "numQubits": 1 }
189190
]
190191
}

pyproject.toml

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ dynamic = ["version"]
4949

5050
[project.optional-dependencies]
5151
qiskit = [
52-
"qiskit[qasm3-import]>=1.0.0",
52+
"qiskit[qasm3-import]>=1.1.0",
5353
]
5454

5555
[project.scripts]
@@ -98,9 +98,7 @@ build.targets = [
9898
"mqt-core-na-bindings",
9999
"mqt-core-qdmi-ddsim-device",
100100
"mqt-core-qdmi-na-device",
101-
"mqt-core-qdmi-na-device-dyn",
102101
"mqt-core-qdmi-sc-device",
103-
"mqt-core-qdmi-sc-device-dyn",
104102
]
105103

106104
install.components = [
@@ -343,7 +341,7 @@ docs = [
343341
"sphinxcontrib-bibtex>=2.6.5",
344342
"sphinxcontrib-svg2pdfconverter>=1.3.0",
345343
"sphinxext-opengraph>=0.13.0",
346-
"qiskit[qasm3-import,visualization]>=1.0.0",
344+
"qiskit[qasm3-import,visualization]>=1.1.0",
347345
"openqasm-pygments>=0.2.0",
348346
"breathe>=4.36.0",
349347
"graphviz>=0.21.0",
@@ -357,7 +355,7 @@ test = [
357355
"pytest-cov>=7.0.0",
358356
"pytest-sugar>=1.1.1",
359357
"pytest-xdist>=3.8.0",
360-
"qiskit[qasm3-import]>=1.0.0",
358+
"qiskit[qasm3-import]>=1.1.0",
361359
"numpy>=2.1; python_version >= '3.13'",
362360
"numpy>=2.3.2; python_version >= '3.14'",
363361
]
@@ -366,5 +364,5 @@ dev = [
366364
{include-group = "test"},
367365
"lit>=18.1.8",
368366
"nox>=2025.11.12",
369-
"ty==0.0.29",
367+
"ty==0.0.34",
370368
]

0 commit comments

Comments
 (0)