Skip to content

✨ MQT QDMI Driver #1010

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 85 commits into
base: qdmi-na-device
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
6e11764
Setup protobuf dep
ystade Jun 4, 2025
5068dc1
Draft doc for NA QDMI device
ystade Jun 4, 2025
09c165b
🎨 Run pre-commit
ystade Jun 4, 2025
8ea4954
🐛 Fix license tool
ystade Jun 4, 2025
a69891d
➕ Add QDMI to the party
ystade Jun 4, 2025
ebbb91b
➕ Add spdlog to the party
ystade Jun 4, 2025
efccd21
✨ Implement device as singleton
ystade Jun 4, 2025
ae26933
🎨 Improve error handling
ystade Jun 4, 2025
c5ba1ad
✅ Setup test infrastructure for qdmi device
ystade Jun 4, 2025
39f00b5
🐛 Fix device and tests
ystade Jun 4, 2025
a33c6d1
🐛 Try to fix some bugs related to QDMI version and protobuf
ystade Jun 4, 2025
8683b1f
🚧 Still fixing protobuf include
ystade Jun 4, 2025
d1b20b1
🐛 Finally fix build
ystade Jun 4, 2025
ae14ffc
🎨 Write out JSON schema
ystade Jun 5, 2025
f7bd8d2
🩹 Fix JSON schema write-out
ystade Jun 5, 2025
081f832
📝 Add comment
ystade Jun 5, 2025
3e89427
🎨 Implement dummy job interface
ystade Jun 5, 2025
69d308c
✅ Fix tests
ystade Jun 5, 2025
bb15426
🎨 Implement querying sites
ystade Jun 5, 2025
bc620b4
✏️ Fix typo
ystade Jun 5, 2025
fb8a952
♻️ Refactor structure and add documentation
ystade Jun 5, 2025
3bba62a
🎨 Implement operations and decoeherence times
ystade Jun 5, 2025
f08b343
🎨 Expose operation properties
ystade Jun 5, 2025
c7b997e
🎨 Restructure file
ystade Jun 5, 2025
abfbb91
🎨 Add shuttling operations
ystade Jun 5, 2025
bd36cbe
🎨 Initialize units
ystade Jun 5, 2025
13b3aa6
🐛 Fix finalize
ystade Jun 5, 2025
25c2163
🐛 Fix test
ystade Jun 5, 2025
d6870ae
🎨 Imrpove naming of tests
ystade Jun 5, 2025
b9dd30d
🍱 Add device.json
ystade Jun 5, 2025
62a32f3
🔥 Remove initialized
ystade Jun 6, 2025
64e6202
🎨 Use add mqt core library
ystade Jun 6, 2025
f5163eb
🚧 Start restructuring
ystade Jun 12, 2025
db022e0
🎨 Update cmake config for gen
ystade Jun 13, 2025
95e3169
✨ First version of generator
ystade Jun 13, 2025
7f20149
🐛 Print proper version
ystade Jun 13, 2025
6da4159
🎨 Resturcture, put everything in device
ystade Jun 13, 2025
f5bb18c
🐛 Fix restructuring
ystade Jun 13, 2025
c97a1a9
🐛 Fix all remaining bugs
ystade Jun 13, 2025
65015da
🔥 Remove outdated docs
ystade Jun 13, 2025
d6c87dd
⏪️ Revert target names
ystade Jun 13, 2025
6984257
🎨 Use unique ptr for sessions
ystade Jun 13, 2025
a374ea2
✅ Incoporate number of qubits
ystade Jun 16, 2025
4ba6c99
🎨 Improve documentation
ystade Jun 16, 2025
2dbc6ac
Potential fix for code scanning alert no. 602: For loop variable chan…
ystade Jun 18, 2025
0bc7165
🔥 Remove superfluous variable
ystade Jun 16, 2025
63895a2
🐛 Fix
ystade Jun 16, 2025
9cba86a
🎨 Incorporate first changes from review
ystade Jun 20, 2025
aa873d4
🎨 Adapt new proto def
ystade Jun 20, 2025
2dcf24b
📝 Add doc page
ystade Jun 20, 2025
e2bf3ca
🎨 Add comment in proto file
ystade Jun 20, 2025
844f776
🎨 Update gen exec
ystade Jun 20, 2025
17d6466
⬆️ Update QDMI
ystade Jun 20, 2025
c9bb86d
🎨 Remove doxygen left-over
ystade Jun 20, 2025
099ecec
Merge remote-tracking branch 'origin/main' into qdmi-na-device
ystade Jun 20, 2025
9142a5b
🐛 Link spdlog header only
ystade Jun 25, 2025
a1a771e
Merge remote-tracking branch 'origin/main' into qdmi-na-device
ystade Jun 25, 2025
2aeba1d
Revert "🐛 Link spdlog header only"
ystade Jun 25, 2025
6dfa4cd
🎨 Add missing header
ystade Jun 25, 2025
85dd973
🎨 Configure protobuf
ystade Jun 25, 2025
b365832
🐛 Fix cmake config
ystade Jun 25, 2025
d73b7a0
🎨 Set install components
ystade Jun 25, 2025
5c049ce
🐛 Export also Development component to export cmake files
ystade Jun 25, 2025
c834a13
🐛 Add header to development target
ystade Jun 25, 2025
1f8fc41
🎨 Keep correct indendation
ystade Jun 25, 2025
79a96dd
📝 Add comment
ystade Jun 25, 2025
75b87c5
✨ Setup One Device Driver
ystade Jun 6, 2025
f6773ca
🚧 Allow multiple devices
ystade Jun 13, 2025
8a7a435
✨ Setup linking known libs as static libs
ystade Jun 16, 2025
f851bc6
🎨 Use unique_ptr for sessions
ystade Jun 16, 2025
5ab0c3c
🎨 Restructure code
ystade Jun 16, 2025
e54dfae
🎨 Add docs
ystade Jun 16, 2025
82c007d
🩹 Fix namespace
ystade Jun 16, 2025
e40c997
✅ Adopt tests from QDMI repo
ystade Jun 16, 2025
9d013ca
🐛 Fix some bugs in tests
ystade Jun 16, 2025
f178f5d
🎨 Update to QDMI 1.2 and Fix Job Parameter setting
ystade Jun 20, 2025
2668be9
✅ Update tests
ystade Jun 20, 2025
9df8d69
📝 Document macros
ystade Jun 23, 2025
87f5e08
🎨 INcoporate some feedback
ystade Jun 23, 2025
cbfaee1
🏗️ Entirely resturcture Driver
ystade Jun 24, 2025
0c2f98d
🐛 Fix tests
ystade Jun 24, 2025
d72979a
📝 Add todo
ystade Jun 24, 2025
b831de9
🎨 Remove getDevice from job
ystade Jun 24, 2025
e84e26a
📝 Improve docs
ystade Jun 25, 2025
80a0e92
🐛 Fix typo
ystade Jun 25, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .license-tools-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
".mlir": "SLASH_STYLE",
".td": "SLASH_STYLE",
".yaml": "POUND_STYLE",
".toml": "POUND_STYLE"
".toml": "POUND_STYLE",
".proto": "SLASH_STYLE"
},
"exclude": [
"^\\.[^/]+",
Expand Down
66 changes: 66 additions & 0 deletions cmake/ExternalDependencies.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,35 @@ else()
list(APPEND FETCH_PACKAGES boost_mp)
endif()

# Abseil is required by GTest and Protobuf. To avoid version conflicts, we add this dependency
# centrally.
set(ABSL_VERSION
20250512.1
CACHE STRING "abseil-cpp version")
set(ABSL_URL https://github.com/abseil/abseil-cpp/archive/refs/tags/${ABSL_VERSION}.tar.gz)
# The install instruction for re2 cannot be disabled and they require the export targets from
# abseil.
set(ABSL_ENABLE_INSTALL
ON
CACHE BOOL "" FORCE)
FetchContent_Declare(abseil-cpp URL ${ABSL_URL} FIND_PACKAGE_ARGS ${ABSL_VERSION} CONFIG NAMES absl)
list(APPEND FETCH_PACKAGES abseil-cpp)

if(BUILD_MQT_CORE_TESTS)
# When adding abseil manually, GTest also requires re2
set(RE2_VERSION
2024-07-02
CACHE STRING "re2 version")
set(RE2_URL https://github.com/google/re2/archive/refs/tags/${RE2_VERSION}.tar.gz)
# remove '-' from version
string(REPLACE "-" "" RE2_VERSION "${RE2_VERSION}")
FetchContent_Declare(re2 URL ${RE2_URL} FIND_PACKAGE_ARGS ${RE2_VERSION} CONFIG)
list(APPEND FETCH_PACKAGES re2)

set(gtest_force_shared_crt
ON
CACHE BOOL "" FORCE)
set(GTEST_HAS_ABSL ON)
set(GTEST_VERSION
1.17.0
CACHE STRING "Google Test version")
Expand All @@ -71,5 +96,46 @@ if(BUILD_MQT_CORE_TESTS)
list(APPEND FETCH_PACKAGES googletest)
endif()

set(Protobuf_VERSION
31.1
CACHE STRING "protobuf version")
set(Protobuf_URL
https://github.com/protocolbuffers/protobuf/releases/download/v${Protobuf_VERSION}/protobuf-${Protobuf_VERSION}.tar.gz
)
# the default of the following is ON, they are just here to make more explicit that they are
# required
set(protobuf_BUILD_PROTOBUF_BINARIES ON)
set(protobuf_BUILD_PROTOC_BINARIES ON)
set(protobuf_BUILD_LIBUPB ON)
# the default of the following is ON, but we do not need the tests
set(protobuf_BUILD_TESTS OFF)
FetchContent_Declare(protobuf URL ${Protobuf_URL} FIND_PACKAGE_ARGS ${Protobuf_VERSION} CONFIG
NAMES protobuf)
list(APPEND FETCH_PACKAGES protobuf)

# cmake-format: off
set(QDMI_VERSION 1.2.0
CACHE STRING "QDMI version")
set(QDMI_REV "9034e653a6e368579d99e352ecd8390e6e947bc6"
CACHE STRING "QDMI identifier (tag, branch or commit hash)")
set(QDMI_REPO_OWNER "Munich-Quantum-Software-Stack"
CACHE STRING "QDMI repository owner (change when using a fork)")
# cmake-format: on
FetchContent_Declare(
qdmi
GIT_REPOSITORY https://github.com/${QDMI_REPO_OWNER}/qdmi.git
GIT_TAG ${QDMI_REV}
FIND_PACKAGE_ARGS ${QDMI_VERSION})
list(APPEND FETCH_PACKAGES qdmi)

set(SPDLOG_VERSION
1.15.3
CACHE STRING "spdlog version")
set(SPDLOG_URL https://github.com/gabime/spdlog/archive/refs/tags/v${SPDLOG_VERSION}.tar.gz)
# Add position independent code for spdlog, this is required for python bindings on linux
set(SPDLOG_BUILD_PIC ON)
FetchContent_Declare(spdlog URL ${SPDLOG_URL} FIND_PACKAGE_ARGS ${SPDLOG_VERSION})
list(APPEND FETCH_PACKAGES spdlog)

# Make all declared dependencies available.
FetchContent_MakeAvailable(${FETCH_PACKAGES})
115 changes: 115 additions & 0 deletions docs/na_qdmi_device.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
---
file_format: mystnb
kernelspec:
name: python3
mystnb:
number_source_lines: true
---

# MQT Core Neutral Atom QDMI Device

## Objective

Compilation passes throughout MQT need information about the target device.
The Neutral Atom QDMI device provides a uniform way to provide the necessary information.
It defines a representation to easily provide static information in the form of a file.

<!-- todo: Explain how to use the device. -->

## Describing a Device

The basis of a device implementation is a specification in a JSON file.
These JSON files are defined on the basis of a protocol buffer schema that can be found in `proto/na/device.proto`.
During compilation, this JSON file is parsed and the corresponding C++ code is produced for the actual QDMI device implementation.
The C++ code is then compiled to a library that can be used by the QDMI driver.

### JSON Schema

An example instance of a device JSON file can be found in `json/na/device.json`.

#### Top-Level Fields

- **`name`** _(string)_: The name of the device.
- **`num_qubits`** _(integer)_: The total number of qubits in the device.
- **`traps`** _(array)_: A list of traps defining the qubit lattice structure.
- **`minAtomDistance`** _(number)_: The minimum distance between atoms in the lattice.
- **`globalSingleQubitOperations`** _(array)_: A list of global single-qubit operations supported by the device.
- **`globalMultiQubitOperations`** _(array)_: A list of global multi-qubit operations supported by the device.
- **`localSingleQubitOperations`** _(array)_: A list of local single-qubit operations supported by the device.
- **`localMultiQubitOperations`** _(array)_: A list of local multi-qubit operations supported by the device.
- **`shuttlingUnits`** _(array)_: A list of shuttling units for moving qubits.
- **`decoherenceTimes`** _(object)_: Decoherence times for the qubits.
- **`lengthUnit`** _(object)_: The unit of length used in the file.
- **`timeUnit`** _(object)_: The unit of time used in the file.

---

#### Detailed Field Descriptions

##### `traps` _(array of objects)_:

- **`latticeOrigin`** _(object)_: The origin of the lattice.
- **`x`** _(number)_: X-coordinate of the origin.
- **`y`** _(number)_: Y-coordinate of the origin.
- **`latticeVector1`** _(object)_: Defines one lattice vector.
- **`vector`** _(object)_: A vector in the lattice.
- **`x`** _(number)_: X-component of the vector.
- **`y`** _(number)_: Y-component of the vector.
- **`repeat`** _(integer)_: Number of repetitions of the vector.
- **`latticeVector2`** _(object)_: Defines the other lattice vector.
- **`vector`** _(object)_: A vector in the lattice.
- **`x`** _(number)_: X-component of the vector.
- **`y`** _(number)_: Y-component of the vector.
- **`repeat`** _(integer)_: Number of repetitions of the vector.
- **`sublatticeOffsets`** _(array of objects)_: Offsets for sublattices.
- **`x`** _(number)_: X-offset.
- **`y`** _(number)_: Y-offset.

##### `globalSingleQubitOperations` and `localSingleQubitOperations` _(array of objects)_:

- **`name`** _(string)_: The name of the operation.
- **`region`** _(object)_: The region where the operation is applied.
- **`origin`** _(object)_: The origin of the region.
- **`x`** _(number)_: X-coordinate of the origin.
- **`y`** _(number)_: Y-coordinate of the origin.
- **`size`** _(object)_: The size of the region.
- **`width`** _(number)_: Width of the region.
- **`height`** _(number)_: Height of the region.
- **`duration`** _(number)_: Duration of the operation.
- **`fidelity`** _(number)_: Fidelity of the operation.
- **`numParameters`** _(integer)_: Number of parameters for the operation.

##### `globalMultiQubitOperations` and `localMultiQubitOperations` _(array of objects)_:

- **`name`** _(string)_: The name of the operation.
- **`region`** _(object)_: The region where the operation is applied (same structure as above).
- **`interactionRadius`** _(number)_: Radius of interaction for the operation.
- **`blockingRadius`** _(number)_: Blocking radius for the operation.
- **`numQubits`** _(integer)_: Number of qubits involved in the operation.
- **`numParameters`** _(integer)_: Number of parameters for the operation.
- **`duration`** _(number)_: Duration of the operation.
- **`fidelity`** _(number)_: Fidelity of the operation.
- **`idlingFidelity`** _(number, optional)_: Fidelity when qubits are idle.

##### `shuttlingUnits` _(array of objects)_:

- **`name`** _(string)_: The name of the shuttling unit.
- **`region`** _(object)_: The region where the shuttling unit operates (same structure as above).
- **`numRows`** _(integer)_: Number of rows in the shuttling unit.
- **`numColumns`** _(integer)_: Number of columns in the shuttling unit.
- **`movingSpeed`** _(number)_: Speed of movement.
- **`loadDuration`** _(number)_: Duration to load a qubit.
- **`storeDuration`** _(number)_: Duration to store a qubit.
- **`loadFidelity`** _(number)_: Fidelity of loading a qubit.
- **`storeFidelity`** _(number)_: Fidelity of storing a qubit.
- **`numParameters`** _(integer)_: Number of parameters for the shuttling unit.

##### `decoherenceTimes` _(object)_:

- **`t1`** _(number)_: Relaxation time (T1) in the specified time unit.
- **`t2`** _(number)_: Dephasing time (T2) in the specified time unit.

##### `lengthUnit` and `timeUnit` _(objects)_:

- **`value`** _(number)_: The scaling factor for the unit.
- **`unit`** _(string)_: The unit of measurement (e.g., "um" for micrometers, "us" for microseconds).
73 changes: 73 additions & 0 deletions include/mqt-core/na/device/Generator.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Copyright (c) 2023 - 2025 Chair for Design Automation, TUM
* Copyright (c) 2025 Munich Quantum Software Company GmbH
* All rights reserved.
*
* SPDX-License-Identifier: MIT
*
* Licensed under the MIT License
*/

#pragma once

#include "na/device/device.pb.h"

#include <istream>
#include <ostream>
#include <string>

namespace na {
/**
* @brief Writes a JSON schema with default values for the device configuration
* to the specified output stream.
* @param os is the output stream to write the JSON schema to.
* @throws std::runtime_error if the JSON conversion fails.
*/
auto writeJSONSchema(std::ostream& os) -> void;

/**
* @brief Writes a JSON schema with default values for the device configuration
* to the specified path.
* @param path The path to write the JSON schema to.
* @throws std::runtime_error if the JSON conversion fails or the file cannot be
* opened.
*/
auto writeJSONSchema(const std::string& path) -> void;

/**
* @brief Parses the device configuration from an input stream.
* @param is is the input stream containing the JSON representation of the
* device configuration.
* @returns The parsed device configuration as a Protobuf message.
* @throws std::runtime_error if the JSON cannot be parsed.
*/
[[nodiscard]] auto readJSON(std::istream& is) -> Device;

/**
* @brief Parses the device configuration from a JSON file.
* @param path is the path to the JSON file containing the device configuration.
* @returns The parsed device configuration as a Protobuf message.
* @throws std::runtime_error if the JSON file does not exist, or the JSON file
* cannot be parsed.
*/
[[nodiscard]] auto readJSON(const std::string& path) -> Device;

/**
* @brief Writes a header file with the device configuration to the specified
* output stream.
* @param device is the protobuf representation of the device.
* @param os is the output stream to write the header file to.
* @throws std::runtime_error if the file cannot be opened or written to.
*/
auto writeHeader(const Device& device, std::ostream& os) -> void;

/**
* @brief Writes a header file with the device configuration to the specified
* path.
* @param device is the protobuf representation of the device.
* @param path is the path to write the header file to.
* @throws std::runtime_error if the file cannot be opened or written to.
*/
auto writeHeader(const Device& device, const std::string& path) -> void;

} // namespace na
Loading
Loading