Contributing¶
Thank you for your interest in contributing to the IQM QDMI Device implementation! This document outlines how to contribute and the development guidelines.
We use GitHub to host code, to track issues and feature requests, as well as accept pull requests. See https://docs.github.com/en/get-started/quickstart for a general introduction to working with GitHub and contributing to projects.
Types of Contributions¶
Pick the path that fits your time and interests:
🐛 Report bugs: Use the 🐛 Bug report template at https://github.com/iqm-finland/QDMI-on-IQM/issues. Include steps to reproduce, expected vs. actual behavior, environment details, and a minimal example.
🛠️ Fix bugs: Browse issues, especially those labeled “bug”, “help wanted”, or “good first issue”. Open a draft PR early to get feedback.
💡 Propose features: Use the ✨ Feature request template at https://github.com/iqm-finland/QDMI-on-IQM/issues. Describe the motivation, alternatives considered, and (optionally) a small API sketch.
✨ Implement features: Pick items labeled “feature” or “enhancement”. Coordinate in the issue first if the change is substantial; start with a draft PR.
📝 Improve documentation: Add or refine docstrings, tutorials, and examples; fix typos; clarify explanations. Small documentation-only PRs are very welcome.
⚡️ Performance and reliability: Profile hot paths, add benchmarks, reduce allocations, deflake tests, and improve error messages.
📦 Packaging and tooling: Improve build configuration, CI workflows, and platform support. Incremental tooling fixes have a big impact.
🙌 Community support: Triage issues, reproduce reports, and answer questions in Discussions.
Guidelines¶
Please adhere to the following guidelines to help the project grow sustainably.
Core Guidelines¶
Write meaningful commit messages, preferably using gitmoji for additional context.
Focus on a single feature or bug at a time and only touch relevant files. Split multiple features into separate contributions.
Add tests for new features to ensure they work as intended.
Document new features. For user-facing changes, consider adding documentation updates to the relevant guides.
Add tests for bug fixes to demonstrate the fix.
Document your code thoroughly and ensure it is readable.
Keep your code clean by removing debug statements, leftover comments, and unrelated code.
Check your code for style and linting errors before committing.
Follow the project’s coding standards and conventions.
Be open to feedback and willing to make necessary changes based on code reviews.
Pull Request Workflow¶
Create PRs early. Work-in-progress PRs are welcome; mark them as drafts on GitHub.
Use a clear title, reference related issues by number, and describe the changes. Follow the PR template; only omit the issue reference if not applicable.
CI runs on all supported platforms to build, test, format, and lint. All checks must pass before merging.
When ready, convert the draft to a regular PR and request a review from a maintainer. If unsure, ask in PR comments. If you are a first-time contributor, mention a maintainer in a comment to request a review.
If your PR gets a “Changes requested” review, address the feedback and push updates to the same branch. Do not close and reopen a new PR. Respond to comments to signal that you have addressed the feedback. Do not resolve review comments yourself; the reviewer will do so once satisfied.
Re-request a review after pushing changes that address feedback.
Do not squash commits locally; maintainers typically squash on merge. Avoid rebasing or force-pushing before reviews; you may rebase after addressing feedback if desired.
Get Started 🎉¶
Ready to contribute? We value contributions from people with all levels of experience. In particular, if this is your first PR, not everything has to be perfect. We will guide you through the process.
Installation¶
Initial Setup¶
Get the code
External Contribution:
If you do not have write access to the iqm-finland/QDMI-on-IQM repository, fork the repository on GitHub (see https://docs.github.com/en/get-started/quickstart/fork-a-repo) and clone your fork locally.
git clone git@github.com:your_name_here/QDMI-on-IQM.gitInternal Contribution:
If you do have write access to the iqm-finland/QDMI-on-IQM repository, clone the repository locally.
git clone git@github.com:iqm-finland/QDMI-on-IQM.gitChange into the project directory
cd QDMI-on-IQMCreate a branch for local development
git checkout -b name-of-your-bugfix-or-featureNow you can make your changes locally.
Install pre-commit hooks (recommended)
The project uses pre-commit hooks for running linters and formatting tools on each commit. These checks can be run automatically on every commit via prek (recommended).
To set this up, install prek, e.g., via:
macOS and Linux:
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/j178/prek/releases/latest/download/prek-installer.sh | shWindows:
powershell -ExecutionPolicy ByPass -c "irm https://github.com/j178/prek/releases/latest/download/prek-installer.ps1 | iex"Using uv:
uv tool install prekThen run:
prek install
Working on the C++ Library¶
Building the project requires a C++20-capable C++ compiler and CMake 3.24 or newer.
Configure and Build¶
This project uses CMake as the main build configuration tool. Building a project using CMake is a two-stage process. First, CMake needs to be configured by calling:
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_IQM_QDMI_TESTS=ON
This tells CMake to:
search the current directory
.(passed via-S) for aCMakeLists.txtfile,process it into a directory
build(passed via-B),configure a
Releasebuild (passed via-DCMAKE_BUILD_TYPE) as opposed to, e.g., aDebugbuild, andenable building the tests (passed via
-DBUILD_IQM_QDMI_TESTS=ON).
Additional useful flags:
-DIQM_QDMI_COVERAGE=ONto enable code coverage support
After configuring with CMake, the project can be built by calling:
cmake --build build --config Release
This builds the project in the build directory (passed via --build). Some
operating systems and development environments explicitly require a
configuration to be set, which is why the --config flag is also passed to the
build command. The flag --parallel <NUMBER_OF_THREADS> may be added to trigger
a parallel build.
Building the project this way generates:
the main project libraries in the
build/srcdirectory andsome test executables in the
build/testdirectory.
Note
This project uses CMake’s
FetchContent
module to download and build its dependencies. The first time you configure the
project, you will need an active internet connection to fetch the required
libraries. Subsequent builds will use the cached dependencies.
Running the C++ Tests and Code Coverage¶
We use the GoogleTest
framework for unit testing of the C++ library. All tests are contained in the
test directory, which is further divided into:
Unit Tests (
test/unit/): Self-contained tests that do not require external dependencies or a live connection to IQM hardware.Integration Tests (
test/integration/): Tests that require a live connection to an IQM backend.
You are expected to write tests for any new features you implement and ensure that all tests pass. Our CI pipeline on GitHub will also run the tests and check for any failures. It will also collect code coverage information and upload it to Codecov. Our goal is to have new contributions at least maintain the current code coverage level, while striving for covering as much of the code as possible. Try to write meaningful tests that actually test the correctness of the code and not just exercise the code paths.
To run the tests, use CMake’s test runner CTest:
Running all tests:
ctest -C Release --test-dir build --output-on-failure
Running only unit tests (no hardware required):
ctest -C Release --test-dir build/test/unit --output-on-failure
Running integration tests (requires IQM access):
Before running the integration tests, make sure you have set the necessary environment variables:
export IQM_BASE_URL="https://desired-iqm-server.com"
export IQM_TOKEN="your-api-key"
ctest -C Release --test-dir build/test/integration --output-on-failure
Generating code coverage:
To generate a code coverage report, configure the project with
-DIQM_QDMI_COVERAGE=ON, build, run the tests, and then use lcov:
cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -DBUILD_IQM_QDMI_TESTS=ON -DIQM_QDMI_COVERAGE=ON
cmake --build build
ctest --test-dir build --output-on-failure
lcov --capture --directory build --output-file coverage.info
lcov --remove coverage.info '/usr/*' '*/test/*' '*/build/_deps/*' --output-file coverage.info
lcov --list coverage.info
C++ Code Formatting and Linting¶
This project mostly follows the LLVM Coding Standard, which is a set of guidelines for writing C++ code. To ensure the quality of the code and that it conforms to these guidelines, we use:
clang-tidy, a static analysis tool that checks for common mistakes in C++ code, andclang-format, a tool that automatically formats C++ code according to a given style guide.
Common IDEs like CLion or
Visual Studio Code have plugins that can
automatically run clang-tidy on the code and automatically format it with
clang-format.
If you are using CLion, you can configure the project to use the
.clang-tidyand.clang-formatfiles in the project root directory.If you are using Visual Studio Code, you can install the clangd extension.
They will automatically execute clang-tidy on your code and highlight any
issues. In many cases, they also provide quick-fixes for these issues.
Furthermore, they provide a command to automatically format your code according
to the given style.
Our pre-commit configuration includes clang-format. If you have installed
prek, it will automatically run clang-format on your code before each
commit. If you do not have prek set up, the
pre-commit.ci bot will run clang-format on your code
and automatically format it according to the style guide.
Tip
Remember to pull the changes back into your local repository after the bot has formatted your code to avoid merge conflicts.
Our CI pipeline will also run clang-tidy over the changes in your PR and
report any issues it finds. Due to technical limitations, the workflow can only
post PR comments if the changes are not coming from a fork. If you are working
on a fork, you can still see the clang-tidy results in the GitHub Actions logs
or on the workflow summary page.
Working on the Python Package¶
The project also comes with a thin Python wrapper around the QDMI device
implementation for easier distribution and integration. The Python package is
located in the python/ directory.
Running the Python tests¶
If you touch the Python package, run the relevant nox sessions before opening
or updating a PR.
Running the full Python test matrix:
uvx nox -s tests
Running a single Python version locally:
uvx nox -s tests-3.14
Running minimum-dependency tests:
The minimums session runs the test suite against the minimum supported
dependency versions for a specific Python version.
uvx nox -s minimums-3.14
Running the Python examples¶
Run the full example suite via the dedicated nox session before opening or updating a PR:
uvx nox -s examples -- --backend sim # simulator (no IQM access required)
uvx nox -s examples # real IQM hardware
For a walkthrough of each example, environment setup, and CLI options, see the Examples guide.
If you touch one of these examples, update the corresponding documentation in examples.md as part of the same change.
Working on the Documentation¶
The documentation is written in Markdown and
built with Sphinx + MyST, using Doxygen XML via Breathe for the C++ API and
AutoAPI for the Python package. The documentation source files can be found in
the docs/ directory.
Writing Documentation¶
We expect any new additions to the code base to be documented using Doxygen comments. When touching existing code, we encourage you to add Doxygen comments to the code you touch or refactor.
For some tips on how to write good Doxygen comments, see the Doxygen Manual.
Documentation improvements are highly valued! This includes:
Adding or improving Doxygen comments in the C++ code
Improving the user guides and tutorials in the
docs/directoryAdding examples and code snippets
Fixing typos and improving clarity
Building the Documentation¶
To build the documentation locally, run the dedicated nox session (dependencies are installed automatically by the nox session):
uvx nox -s docs
The generated HTML site is written to docs/_build/html/.
Tips for Development¶
If something goes wrong, the CI pipeline will notify you. Here are some tips for finding the cause of certain failures:
If any of the test checks fail, this indicates build errors or test failures. Look through the respective logs on GitHub for any error or failure messages.
If codecov checks fail, this means that your changes are not appropriately covered by tests or that the overall project coverage decreased too much. Ensure that you include tests for all your changes in the PR.
If cpp-linter comments on your PR with a list of warnings, these have been raised by
clang-tidywhen checking the C++ part of your changes for warnings or style guideline violations. The individual messages frequently provide helpful suggestions on how to fix the warnings.If the pre-commit.ci check fails, some of the
pre-commitchecks failed and could not be fixed automatically by the pre-commit.ci bot. The individual log messages frequently provide helpful suggestions on how to fix the warnings.If the documentation build fails, the documentation could not be built properly. Inspect the corresponding log file for any errors.
IQM API Usage in QDMI Device Implementation¶
This section describes how the unified IQM Server API, as defined in
iqm_api_config.hpp and iqm_api_config.cpp, is used to provide the
functionality of the QDMI device implementation in iqm_device.cpp.
API Endpoints Used¶
The QDMI device implementation uses the following endpoints from the unified IQM Server API:
Quantum Computer Management:
GET_QUANTUM_COMPUTERS: Retrieves the list of available quantum computers with their IDs and aliases.GET_STATIC_QUANTUM_ARCHITECTURE: Fetches the static quantum architecture (qubits and connectivity) for a specific quantum computer.GET_DYNAMIC_QUANTUM_ARCHITECTURE: Obtains the set of calibrated gates and their implementations for a given calibration set.GET_CALIBRATION_SET_QUALITY_METRICS: Gets calibration metrics such as qubit T1/T2 times and gate fidelities.
Job Management:
SUBMIT_CIRCUIT_JOB: Submits a quantum circuit job (QIR or IQM JSON format) for execution.GET_JOB_STATUS: Checks the status of a submitted job.GET_JOB_ARTIFACT_MEASUREMENT_COUNTS: Retrieves the measurement results as aggregated histogram counts of a completed job.GET_JOB_ARTIFACT_MEASUREMENTS: Retrieves the individual shot measurement results of a completed job.CANCEL_JOB: Cancels a running job.
Calibration Jobs (if supported):
COCOS_HEALTH: Health check endpoint to determine if calibration jobs are supported.SUBMIT_CALIBRATION_JOB: Submits a calibration job for execution.GET_CALIBRATION_JOB_STATUS: Checks the status of a calibration job.ABORT_CALIBRATION_JOB: Cancels a running calibration job.
When API Calls Happen¶
During Session Initialization (IQM_QDMI_device_session_init):
These steps correspond to the initialization sequence described in the Usage Guide.
GET_QUANTUM_COMPUTERS: Fetches the list of available quantum computers.The appropriate quantum computer is selected based on ID, alias, or first available.
GET_STATIC_QUANTUM_ARCHITECTURE: Retrieves the static architecture (qubits, connectivity).GET_DYNAMIC_QUANTUM_ARCHITECTURE: Fetches calibrated gates for the default calibration set.GET_CALIBRATION_SET_QUALITY_METRICS: Retrieves quality metrics (T1, T2, fidelities) if available.COCOS_HEALTH: Checks whether calibration jobs are supported.
During Job Submission and Management:
SUBMIT_CIRCUIT_JOBorSUBMIT_CALIBRATION_JOB: Called whenIQM_QDMI_device_job_submitis invoked.GET_JOB_STATUSorGET_CALIBRATION_JOB_STATUS: Polled whenIQM_QDMI_device_job_checkorIQM_QDMI_device_job_waitis called.GET_JOB_ARTIFACT_MEASUREMENT_COUNTS: Fetched when histogram results are queried.GET_JOB_ARTIFACT_MEASUREMENTS: Fetched when individual shot results are queried.CANCEL_JOBorABORT_CALIBRATION_JOB: Called whenIQM_QDMI_device_job_cancelis invoked.
After Calibration Job Completion:
When querying results of a calibration job, the implementation automatically:
Extracts the new calibration set ID from the job result.
Calls
GET_DYNAMIC_QUANTUM_ARCHITECTUREwith the new calibration set ID.Calls
GET_CALIBRATION_SET_QUALITY_METRICSto update quality metrics.
API Configuration¶
The APIConfig class in iqm_api_config.hpp provides a centralized way to
build URLs for API endpoints. The base URL is set during session initialization,
and endpoints are constructed using string formatting with parameters like
quantum computer alias, calibration set ID, and job ID.
Error Handling¶
If an API call fails, the HTTP client returns an appropriate QDMI status code.
Error messages are logged using the logging system.
For calibration job endpoints, if the server doesn’t support them (e.g.,
COCOS_HEALTHcheck fails), thesupports_calibration_jobs_flag is set to false, and calibration job submissions will returnQDMI_ERROR_NOTSUPPORTED.
API Response Expectations¶
The implementation expects JSON responses in specific formats:
Quantum Computers List: Array of objects with
idandaliasfields.Static Architecture: Array with a single object containing
qubits(array of strings) andconnectivity(array of 2-element arrays).Dynamic Architecture: Object with
calibration_set_id(string) andgates(nested objects with gate details).Quality Metrics: Object with
observationsarray containingdut_field,value, andinvalidfields.Job Status: Object with job status, errors, and messages.
Measurement Counts Artifact: Array with a single object containing
counts(object mapping bitstrings to count integers).Measurements Artifact: Array typically containing a single object where each measurement key maps to an array of all shot results. Each shot result is a single-element array containing an integer (0 or 1). For example:
[{"meas_2_0_0": [[0], [1], [0], [1]], "meas_2_0_1": [[1], [0], [1], [0]]}]represents 4 shots measuring two qubits, where each measurement key contains all results for that qubit across all shots.
For more details, see the implementation in iqm_device.cpp and the API
configuration in iqm_api_config.hpp/.cpp.
Security¶
If you discover a security vulnerability, please follow the guidelines in our Security Policy to report it responsibly.
Questions?¶
If you have any questions about contributing, feel free to:
Open an issue with the “question” label
Start a discussion in GitHub Discussions
Reach out to the maintainers directly
Thank you for contributing to the IQM QDMI Device implementation! 🎉