QDMI v1.3.4-dev
Quantum Device Management Interface
Loading...
Searching...
No Matches
Upgrade Guide

This document describes breaking changes and provides guidance for upgrading between versions. For a complete list of changes, including minor and patch releases, please refer to the changelog.

Unreleased

Program-format execution features

QDMI replaces the program-format enum with an exact QDMI_Program_Format descriptor. The descriptor contains an ID, packed Semantic Versioning release, profile, and text or binary encoding. Devices list every accepted descriptor in QDMI_DEVICE_PROPERTY_SUPPORTEDPROGRAMFORMATS. Clients must submit one of those exact values and must not infer version compatibility. Descriptor identity is a value contract: callers can reconstruct a canonical value and compare it with QDMI_program_format_equal.

const QDMI_Program_Format qasm3 = {
QDMI_MAKE_VERSION(3, 0, 0), QDMI_PROGRAM_ENCODING_TEXT, "openqasm", ""};
#define QDMI_MAKE_VERSION(major, minor, patch)
Pack a Semantic Versioning major, minor, and patch release into a 32-bit exact version value.
Definition constants.h:945
@ QDMI_PROGRAM_ENCODING_TEXT
Text with exactly one trailing NUL and no earlier NUL.
Definition constants.h:959
Exact program format accepted by a device.
Definition constants.h:1031

Text payloads contain exactly one trailing NUL and no earlier NUL; their size includes that NUL. Binary payloads are nonempty arbitrary byte sequences.

QDMI reserves the unqualified IDs openqasm and qir for standard formats. Vendor formats use <vendor>.<custom-format-identifier> IDs such as iqm.circuit; the vendor component is not a reverse domain name.

Use the following replacements for the removed enum values:

Removed value QDMI_Program_Format replacement
QDMI_PROGRAM_FORMAT_QASM2 {QDMI_MAKE_VERSION(2, 0, 0), QDMI_PROGRAM_ENCODING_TEXT, "openqasm", ""}
QDMI_PROGRAM_FORMAT_QASM3 {QDMI_MAKE_VERSION(3, 0, 0), QDMI_PROGRAM_ENCODING_TEXT, "openqasm", ""}
QDMI_PROGRAM_FORMAT_QIRBASESTRING {QDMI_MAKE_VERSION(1, 0, 0), QDMI_PROGRAM_ENCODING_TEXT, "qir", "base"}
QDMI_PROGRAM_FORMAT_QIRBASEMODULE {QDMI_MAKE_VERSION(1, 0, 0), QDMI_PROGRAM_ENCODING_BINARY, "qir", "base"}
QDMI_PROGRAM_FORMAT_QIRADAPTIVESTRING {QDMI_MAKE_VERSION(1, 0, 0), QDMI_PROGRAM_ENCODING_TEXT, "qir", "adaptive"}
QDMI_PROGRAM_FORMAT_QIRADAPTIVEMODULE {QDMI_MAKE_VERSION(1, 0, 0), QDMI_PROGRAM_ENCODING_BINARY, "qir", "adaptive"}
QDMI_PROGRAM_FORMAT_QPY No standard replacement; providers must document a vendor-namespaced descriptor
QDMI_PROGRAM_FORMAT_IQMJSON A provider-defined descriptor with a namespaced ID
QDMI_PROGRAM_FORMAT_CALIBRATION No descriptor; use a provider extension to trigger calibration
QDMI_PROGRAM_FORMAT_BATCHJOB No descriptor; use QDMI_job_set_programs
QDMI_PROGRAM_FORMAT_CUSTOM1 through CUSTOM5 A provider-defined descriptor with a namespaced ID
QDMI_PROGRAM_FORMAT_MAX No replacement

QDMI defines no version, profile, wire, or result semantics for the removed QPY and IQM JSON values. A provider can expose either format with a vendor-namespaced descriptor and must document that descriptor and its payload and result contract.

The QIR replacements above preserve the QIR 1.0 meaning of the removed enum values. A current QIR 2.1 descriptor instead uses QDMI_MAKE_VERSION(2, 1, 0). The descriptor version identifies the QIR specification and is independent of the version in a QIR output-schema stream.

Standard descriptors define exact mappings. They filter zone sites from QDMI_DEVICE_PROPERTY_SITES and preserve the provider order of the remaining regular sites. OpenQASM quantum instructions match a reported local operation by name, qubit arity, and parameter arity. OpenQASM q[i] maps to the i-th regular site, while OpenQASM 3 $i maps by QDMI_SITE_PROPERTY_INDEX to a regular site. A QIR function named __quantum__qis__NAME__body matches the reported local operation named NAME, with the same qubit and parameter arity. Statically identified QIR qubits map by QDMI_SITE_PROPERTY_INDEX to regular sites. A device that advertises QIR must assign the regular sites exactly the index set [0, N), where N is QDMI_DEVICE_PROPERTY_QUBITSNUM. Format- or profile-mandated measurement, output, and runtime primitives do not need corresponding operation records. The standard mappings do not define how a payload selects a zoned operation.

The new QDMI_device_session_query_program_features device function and QDMI_device_query_program_features client function query optional execution features for one exact descriptor. A successful query returns the complete list of optional QDMI_Program_Feature records. A successful empty query means that only the format's normative baseline is supported. QDMI_ERROR_NOTSUPPORTED means that feature metadata is unknown. Boolean features use value zero. Width features, such as integer computation, use one feature group per supported width. A standard descriptor does not imply support for every construct that its source format can express.

Use QDMI_PROGRAM_FEATURE_UNCONSTRAINED(id, value) to initialize an unrestricted feature without naming the constraint fields. Repeated records for one feature and value add conjunctive typed constraints. QDMI initially defines maximum control-flow nesting depth, loop iteration count, and multiway case count. A client must treat a known feature group as unusable if any constraint is unknown, malformed, duplicated, or not defined for that feature.

Device plugins and clients must use matching minor-version headers. A QDMI 1.3 client must not pass an enum value to a QDMI 1.4 device, and a QDMI 1.4 client must not call the new query on a QDMI 1.3 device.

Calibration and batch submission are no longer program formats. QDMI_DEVICE_PROPERTY_NEEDSCALIBRATION remains available, but QDMI does not define a portable calibration trigger. Use QDMI_job_set_programs to submit an ordered program list as one job. One exact format, shot count, lifecycle, and job ID apply to the complete list. Retrieve each result with QDMI_job_get_results; its program index matches the input order. A support probe passes programs == NULL and a nonzero count. It succeeds only for that exact descriptor and cardinality and does not change the job. Text programs contain exactly one trailing NUL. Binary programs are arbitrary nonempty byte sequences.

QDMI_JOB_PARAMETER_PROGRAM and QDMI_DEVICE_JOB_PARAMETER_PROGRAM were removed. Use QDMI_job_set_programs and QDMI_device_job_set_programs for both single- and multi-program jobs. Setting the same QDMI_JOB_PARAMETER_PROGRAMFORMAT keeps the payload. Setting a different supported format clears the payload. Failed setters leave the complete prior state unchanged. QDMI_JOB_PROPERTY_PROGRAMSNUM returns QDMI_ERROR_BADSTATE until a payload is set and then reports the exact count.

The result getter now takes a zero-based program index:

int QDMI_job_get_results(QDMI_Job job, size_t program_index,
QDMI_Job_Result result, size_t size, void *data,
size_t *size_ret);
enum QDMI_JOB_RESULT_T QDMI_Job_Result
Job result type.
Definition constants.h:1383
int QDMI_job_get_results(QDMI_Job job, size_t program_index, QDMI_Job_Result result, size_t size, void *data, size_t *size_ret)
Retrieve one program's results from a job.
struct QDMI_Job_impl_d * QDMI_Job
A handle for a client-side job.
Definition client.h:645

Use index zero for a single-program job. A multi-program job exposes no partial results. Retrieval by job ID succeeds only when the implementation can restore the exact historical descriptor, program count, aggregate status, and result index mapping. Otherwise, it returns QDMI_ERROR_NOTSUPPORTED.

QDMI_JOB_RESULT_SHOTS and histogram keys now describe payload-declared flat bit outputs. OpenQASM 2 uses creg declarations in source order. OpenQASM 3 uses explicit bit-valued outputs, or the language's implicit outputs when none are declared. Both use increasing bit indices within each declaration. QIR uses primitive result-recording call order. These rules assign logical slots from zero. Strings write the highest slot first and slot zero at the right, so slot values [1, 0, 0] produce "001". The payload schema owns the slots; their width and order are independent of device sites. Logical qubit zero remains the least-significant basis bit for state and probability results. A provider returns QDMI_ERROR_NOTSUPPORTED when an output cannot be represented losslessly as a fixed-width bit string. QDMI_JOB_RESULT_PROGRAMOUTPUT returns a format-defined output byte sequence when a flat bit result cannot represent the payload result. A QIR specification that defines an output schema uses a complete output-schema stream for every shot. Older QIR or provider-defined descriptors can return QDMI_ERROR_NOTSUPPORTED. The byte sequence need not be NUL-terminated.

On the client interface, job properties report the exact descriptor submitted by the client. On the device interface, they report the descriptor executed by the device. A translating driver must retain this mapping, including for job retrieval, or reject retrieval with QDMI_ERROR_NOTSUPPORTED. A retrieved job can report its historical descriptor after the device stops advertising that descriptor.

Each QDMI enum with CUSTOM members reserves the inclusive range from 999999995 through INT32_MAX for provider-defined values. The existing CUSTOM1 through CUSTOM5 names remain aliases for the first five values. Values between an enum's regular MAX member and 999999995 are invalid; unrecognized values in the custom range are valid inputs that return QDMI_ERROR_NOTSUPPORTED.

Required device job symbols

Every QDMI 1.4 device library must export QDMI_device_session_retrieve_device_job_by_id and QDMI_device_job_set_programs. The existing QDMI_device_job_get_results export now takes a program index. A device can return QDMI_ERROR_NOTSUPPORTED from retrieval or a program-list support probe when it cannot provide the complete contract. Drivers no longer accept missing symbols. Add stubs and update the result-getter signature before rebuilding an older device library against the QDMI 1.4 headers.

1.3.3

Retrieving existing jobs by ID

Jobs can now be retrieved by their ID via the new functions QDMI_session_retrieve_job_by_id (client interface) and QDMI_device_session_retrieve_device_job_by_id (device interface). The ID is the one reported by QDMI_JOB_PROPERTY_ID and QDMI_DEVICE_JOB_PROPERTY_ID, respectively.

A retrieved job can be queried, waited for, cancelled, and used to fetch results, but its parameters cannot be set and it cannot be submitted again. Devices that do not support this must return QDMI_ERROR_NOTSUPPORTED.

Optional queue properties

Two optional properties have been added:

Both are optional; implementations that cannot provide a trustworthy value return QDMI_ERROR_NOTSUPPORTED.

Stable device IDs and symbol prefixes exported from device targets

Device targets can now publish their stable ID and symbol prefix via the new configure_qdmi_device_target CMake function, which sets and exports the QDMI_DEVICE_ID and QDMI_DEVICE_PREFIX target properties.

configure_qdmi_device_target(TARGET my_device ID "my.default" PREFIX "MY")

Newly generated projects use this by default and expose an overridable <PREFIX>_QDMI_DEVICE_ID cache variable that defaults to <lowercase-prefix>.default. Existing device implementations can adopt it by calling the function for their device target. Once distributed, the ID should remain stable so that applications can keep referring to the same device.

1.3.2

Child device representations in a multicore architecture

The type used to represent core / processing-unit related information has been changed. A new device library implementation specific opaque pointer type named QDMI_Child_Device has been introduced for the QDMI_DEVICE_PROPERTY_CHILDDEVICES data queried via the device_query_interface.

  • Authors of a multicore device library must change the internal type used to represent child devices accordingly.
  • Authors of a driver library are now free to implement the client related type QDMI_Device without device library related constraints.

CMake presets

CMake presets have been added to provide a standardized and reproducible way to configure builds across different platforms. These presets are also used in our CI.

On Unix systems, the debug, release, and coverage presets can be used to configure, build, and test QDMI.

cmake --preset release
cmake --build --preset release
ctest --preset release

Additionally, the lint preset can be used to configure and build QDMI in preparation for a clang-tidy run.

1.3.1

Support for multicore architectures

This release adds three new properties and parameters to the interface to enable support for multicore architectures:

  • QDMI_DEVICE_PROPERTY_CHILDDEVICES: A device property that allows clients to query the child devices (cores, processing units, etc.) of a top-level device. This enables clients to retrieve relevant information about each child device, such as its status and fidelity data.
  • QDMI_DEVICE_SESSION_PARAMETER_CHILDDEVICE: A session parameter that allows clients to specify the child device to use when creating a session. This ensures correct handling of the child device handle in the QDMI driver.
  • QDMI_PROGRAM_FORMAT_BATCHJOB: A new program format that allows clients to submit a batch job that combines multiple jobs for different child devices into a single batch via the top-level device. This enables the top-level device to manage and synchronize job execution across all child devices.

The respective changes are additive and non-breaking, but device implementations that want to support multicore architectures will need to implement the new properties and parameters.

1.3.0

No need to link devices against the QDMI header-only library

As of this release, the QDMI header-only library is no longer required to be linked into QDMI device implementations. Instead, each QDMI device now bundles all necessary headers in its own include directory. This allows distributing any QDMI device implementation in a truly standalone manner. You can remove the qdmi::qdmi target from the CMake configuration of your device implementation.

To properly resolve the imports, you will need to adjust the header includes in your device implementation. Any include of the form

#include <qdmi/constants.h>
Defines constants and value types used within QDMI across the QDMI Client Interface and the QDMI Devi...

must be replaced with

#include <my_qdmi/constants.h>

where my is the prefix of your device implementation.

New header for managing exported symbols of device implementations

Device implementations may now be compiled with hidden symbol visibility, which is a common best practice for C++ libraries to reduce symbol clashes and improve load times. In practice, this means that only symbols explicitly marked for export are accessible from outside the device library.

The header my_qdmi/export.h (where my is your device prefix) provides the export macro MY_QDMI_EXPORT. Use this header to control, which symbols are part of your public API.

All QDMI interface functions are already marked for export in my_qdmi/device.h. You only need to add MY_QDMI_EXPORT manually for additional custom public functions.

To enable this behavior, add the following CMake code to your device target's configuration:

target_compile_definitions(${QDMI_TARGET_NAME} PRIVATE MY_QDMI_device_EXPORTS)
set_target_properties(${QDMI_TARGET_NAME} PROPERTIES
C_VISIBILITY_PRESET hidden
CXX_VISIBILITY_PRESET hidden
VISIBILITY_INLINES_HIDDEN 1)

where MY is your device prefix.

1.2.2

Updated QDMI device template

The QDMI device template has been updated to be compatible with the latest version of the QDMI specification and to include several improvements. Most importantly, as described above, the device implementation no longer needs to link against the QDMI header-only library and is now built with hidden symbol visibility by default.

Beyond that, the template has been extended to include:

  • More precise licensing information
  • A default cache-keys setup for uv to enable automatic rebuilds
  • A more user-friendly CLI with exclusive groups for the CLI options
  • More default cibuildwheel configuration for broad macOS compatibility and Windows wheel repairs
  • Symbol exports on Windows to ensure the device DLL exposes all symbols
  • Fixes for the installation instructions so that component-based installation works correctly
  • Fixes for running tests on Windows
  • Easier coverage collection configuration via the new qdmi::qdmi_coverage_flags target

1.2.1

Fix for using Installed Version of QDMI

In order to avoid a mismatch in the target name for the qdmi_project_warnings target between the source and installed versions of QDMI, the target alias has been adjusted. If your project relies on qdmi::project_warnings, you need to change it to qdmi::qdmi_project_warnings. More rationale is available in the PR description.

Changes to Prefix Handling

The CMake functionality for handling the prefixing of QDMI devices was refactored to improve the usability and flexibility. Particularly, the generate_device_defs_executable CMake function has been changed to allow the optional specification of the QDMI device target to link via a TARGET keyword argument. Example usage:

generate_device_defs_executable("my_prefix" TARGET my_device)

This change is expected to be fully backwards compatible.

Updated QDMI device template

The QDMI device template has been significantly updated to be more useful and provide a fully fletched starting point for new devices. This includes updating the existing template code with the latest best practices, including updating the CMake version range to 3.24-4.2 and using C++20 features.

In addition to these basic changes, the template has been extended to include:

  • installation instructions for the device library
  • boilerplate documentation infrastructure
  • a thin Python wrapper for distributing the device implementation
  • linter and formatter configuration
  • automatic license header generation
  • and more.

The corresponding documentation has been updated to reflect these changes.

In addition, the template instantiation workflow has changed: the template files are no longer written as a side effect of the CMake configure step. Instead, configuration only defines the prefix and output path, and the actual file generation happens when the explicit build target qdmi-template is invoked (use qdmi-template-clean to overwrite an existing output directory).

1.2.0

Version 1.2.0 introduces several breaking changes, primarily related to type system improvements, duration/length unit handling, and API enhancements for neutral atom devices. Please review all sections carefully when upgrading.

New Program Formats (Non-Breaking)

Two new program formats were added to the QDMI_Program_Format enum to support additional quantum programming frameworks:

  • QDMI_PROGRAM_FORMAT_QPY: Binary representation of a Qiskit QuantumCircuit using the QPY format
  • QDMI_PROGRAM_FORMAT_IQMJSON: IQM's proprietary data transfer format serialized as JSON

These additions are backward-compatible and do not require changes to existing code.

Units for Length and Duration (Breaking Change)

Breaking Change: Length and duration properties now use integer types (int64_t or uint64_t) instead of double, and represent values in device-specific units rather than standard SI units.

What Changed

  • All duration-related properties now return integer values in device-specific units
  • All length-related properties now return integer values in device-specific units
  • The raw integer values must be interpreted using unit metadata provided by the device

Required Changes for Device Implementations

Device implementations must now provide the following properties to define their unit system:

Migration Example

Before (v1.1.0):

double t1;
device, site, QDMI_SITE_PROPERTY_T1, sizeof(double), &t1, nullptr);
// T1 time in us
@ QDMI_SITE_PROPERTY_T1
uint64_t The raw, unscaled T1 time of a site.
Definition constants.h:567
int QDMI_device_query_site_property(QDMI_Device device, QDMI_Site site, QDMI_Site_Property prop, size_t size, void *value, size_t *size_ret)
Query a site property.

After (v1.2.0):

uint64_t t1 = 0;
device, site, QDMI_SITE_PROPERTY_T1, sizeof(uint64_t), &t1, nullptr);
double scale_factor = 0.0;
&scale_factor, nullptr);
// T1 time in device duration units
double t1_in_device_units = static_cast<double>(t1) * scale_factor;
@ QDMI_DEVICE_PROPERTY_DURATIONSCALEFACTOR
double A scale factor for all duration values.
Definition constants.h:429
int QDMI_device_query_device_property(QDMI_Device device, QDMI_Device_Property prop, size_t size, void *value, size_t *size_ret)
Query a device property.

To get the device's duration unit, use the QDMI_DEVICE_PROPERTY_DURATIONUNIT property.

size_t size = 0;
device, QDMI_DEVICE_PROPERTY_DURATIONUNIT, 0, nullptr, &size);
std::string unit(size - 1, '\0');
device, QDMI_DEVICE_PROPERTY_DURATIONUNIT, size, unit.data(),
nullptr);
@ QDMI_DEVICE_PROPERTY_DURATIONUNIT
char* (string) The duration unit reported by the device.
Definition constants.h:419

Property Naming and New Properties (Partially Breaking)

Breaking Change: Property Rename

Migration: Replace all occurrences of QDMI_SITE_PROPERTY_ID with QDMI_SITE_PROPERTY_INDEX in your codebase.

New Properties (Non-Breaking)

Neutral Atom Device Properties (Non-Breaking)

Version 1.2.0 adds comprehensive support for neutral atom quantum computing platforms through a set of new device, site, and operation properties. These additions are non-breaking and optional for non-neutral-atom devices.

Device-Level Properties

Site-Level Properties

Operation-Level Properties

These properties enable precise modeling of neutral atom device capabilities.

Job Property Query and Timeout (Breaking Change)

New Job Property Query Functions (Non-Breaking)

Two new functions have been added for querying job properties:

These functions allow clients to retrieve job metadata and previously set parameter values, enabling better job tracking and debugging.

Breaking Change: Timeout Parameter Required

Breaking Change: The functions QDMI_job_wait and QDMI_device_job_wait now require an additional timeout parameter.

Function Signatures:

// Before (v1.1.0)
// After (v1.2.0)
int QDMI_job_wait(QDMI_Job job, size_t timeout);
int QDMI_device_job_wait(QDMI_Device_Job job, size_t timeout);
int QDMI_job_wait(QDMI_Job job, size_t timeout)
Wait for a job to finish.
int QDMI_device_job_wait(QDMI_Device_Job job, size_t timeout)
Wait for a job to finish.
struct QDMI_Device_Job_impl_d * QDMI_Device_Job
A handle for a device job.
Definition device.h:487

Timeout Parameter:

  • Type: size_t
  • Unit: Seconds
  • Value 0: Wait indefinitely (equivalent to old behavior)
  • Non-zero: Maximum wait time in seconds
  • New return code: QDMI_ERROR_TIMEOUT when timeout expires before job completion

Migration:

// To maintain v1.1.0 behavior (indefinite wait):
QDMI_job_wait(job, 0);
// Or specify an explicit timeout (e.g., 30 seconds):
int ret = QDMI_job_wait(job, 30);
if (ret == QDMI_ERROR_TIMEOUT) {
// Handle timeout case
}
@ QDMI_ERROR_TIMEOUT
Operation timed out.
Definition constants.h:56

Authentication Options (Breaking Change)

New Authentication Parameters (Non-Breaking)

Four new authentication options have been added to QDMI_SESSION_PARAMETER and QDMI_DEVICE_SESSION_PARAMETER enums to support diverse authentication mechanisms:

Breaking Change: Enum Value Ordering

Breaking Change: The addition of new authentication options has changed the numeric values of existing enum entries in QDMI_SESSION_PARAMETER and QDMI_DEVICE_SESSION_PARAMETER.

Impact:

  • Code that relies on specific numeric values of enum constants will break
  • Code using the enum symbolic names will continue to work correctly

Migration:

  • Recommended: Always use symbolic enum names (e.g., QDMI_SESSION_PARAMETER_HOST) rather than numeric values
  • If numeric values were stored or transmitted, update serialization/deserialization code to use version-aware mapping

Device Implementation Requirements:

  • Device implementations should document the authentication parameters they support
  • Unsupported parameters should return QDMI_ERROR_NOTSUPPORTED
  • New parameters are optional; existing authentication mechanisms remain valid

Job Status Enum Updates (Breaking Change)

Breaking Change: The QDMI_JOB_STATUS enum values have been reordered to better reflect the typical job lifecycle progression.

Impact:

  • Code relying on numeric values of QDMI_JOB_STATUS enum constants will break
  • Code using symbolic names will continue to work correctly

Migration:

  • Use symbolic enum names (e.g., QDMI_JOB_STATUS_QUEUED) instead of numeric values
  • Review any code that performs numeric comparisons or ordering of job status values
  • Update serialization/deserialization code to be version-aware

CMake Version Requirement (Breaking Change)

Breaking Change: The minimum required CMake version has been raised from 3.19 to 3.24.

Migration:

  • Update your CMake installation to version 3.24 or later
  • Update CI/CD pipelines and build documentation to reflect the new requirement
  • Most modern Linux distributions and development environments provide CMake 3.24+

Rationale: This change enables better build system features and improved dependency management.

Summary of Breaking Changes

For quick reference, here are all breaking changes in v1.2.0:

  1. Duration/length properties: Changed from double to integer types with device-specific units
  2. QDMI_SITE_PROPERTY_ID: Renamed to QDMI_SITE_PROPERTY_INDEX
  3. Job wait functions: Now require timeout parameter
  4. QDMI_SESSION_PARAMETER enums: Reordered due to new authentication options
  5. QDMI_JOB_STATUS enum: Reordered to reflect job lifecycle
  6. CMake: Minimum version raised to 3.24