Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
647afa0
Support dynamic quantum architecture for IQM QPUs
iqm-bhoffmann Aug 4, 2025
b473371
Pull updates from branch main
iqm-bhoffmann Aug 4, 2025
09162a9
Merge branch 'main' into support-iqm-dynamic-quantum-architecture
sacpis Aug 4, 2025
63828da
removing yapf as spell checker is complaining about it
sacpis Aug 4, 2025
9914c16
Removed debug prints which are failing
iqm-bhoffmann Aug 5, 2025
30e7ddd
Merge branch 'main' into support-iqm-dynamic-quantum-architecture
sacpis Aug 5, 2025
56c5e17
Removed commented-out debug prints entirely
iqm-bhoffmann Aug 5, 2025
3f0d099
Merge branch 'main' into support-iqm-dynamic-quantum-architecture
sacpis Aug 5, 2025
1067441
Fixed emulation mode for IQM server
iqm-bhoffmann Aug 8, 2025
403d4ed
Merge branch 'main' into support-iqm-dynamic-quantum-architecture
iqm-bhoffmann Aug 11, 2025
a472db4
Fixed mapping file issue for emulation mode
iqm-bhoffmann Aug 12, 2025
41a4ce7
Merge branch 'main' into support-iqm-dynamic-quantum-architecture
sacpis Aug 12, 2025
2bbc8f0
Merge branch 'NVIDIA:main' into support-iqm-dynamic-quantum-architecture
iqm-bhoffmann Aug 13, 2025
cc3e9e0
Merge branch 'main' into support-iqm-dynamic-quantum-architecture
sacpis Aug 13, 2025
c922993
Merge branch 'main' into support-iqm-dynamic-quantum-architecture
iqm-bhoffmann Aug 14, 2025
5b6c2e8
Merge branch 'main' into support-iqm-dynamic-quantum-architecture
iqm-bhoffmann Aug 18, 2025
e0559db
Corrected comments and code readability
iqm-bhoffmann Aug 18, 2025
a59cfb3
Correction from clang-format
iqm-bhoffmann Aug 18, 2025
cd84da0
Merge branch 'main' into support-iqm-dynamic-quantum-architecture
iqm-bhoffmann Aug 19, 2025
fb5bf88
Merge branch 'main' into support-iqm-dynamic-quantum-architecture
sacpis Aug 19, 2025
48495aa
Merge branch 'main' into support-iqm-dynamic-quantum-architecture
sacpis Aug 20, 2025
6e7131f
Merge branch 'main' into support-iqm-dynamic-quantum-architecture
sacpis Aug 20, 2025
2a97e5c
Remove again `prx` from spellchecker whitelist
iqm-bhoffmann Sep 26, 2025
c5a6e45
Clarified documentation
iqm-bhoffmann Sep 26, 2025
7d19320
Alternate ways to define the IQM QPU architecture
iqm-bhoffmann Oct 10, 2025
604f3d2
Updated IQM doc, save DQA to file, tests
iqm-bhoffmann Nov 6, 2025
2fb66ab
Merge branch main
iqm-bhoffmann Nov 10, 2025
6cc51c2
Merge branch 'main' into support-iqm-dynamic-quantum-architecture
sacpis Nov 11, 2025
47e9c5c
Fixup lint and linkcheck issues
iqm-bhoffmann Nov 11, 2025
33d562b
Merge remote branch 'support-iqm-dynamic-quantum-architecture'
iqm-bhoffmann Nov 11, 2025
58de041
Merge branch 'main' into support-iqm-dynamic-quantum-architecture
sacpis Nov 12, 2025
5fb249a
Merge branch 'main' into support-iqm-dynamic-quantum-architecture
bettinaheim Nov 12, 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
1 change: 1 addition & 0 deletions .github/workflows/config/spelling_allowlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,7 @@ toolchain
toolchains
toolset
transmon
transpile
trotterization
uccsd
unary
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/integration_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -637,7 +637,7 @@ jobs:
;;

iqm)
nvq++ -DSYNTAX_CHECK --target iqm --iqm-machine Crystal_5 $filename
nvq++ -DSYNTAX_CHECK --target iqm $filename
test_status=$?
if [ $test_status -eq 0 ]; then
./a.out
Expand Down
14 changes: 7 additions & 7 deletions .github/workflows/test_in_devenv.yml
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ jobs:
shell: bash
run: |
cd $CUDAQ_REPO_ROOT
python3 -m pip install iqm-client==16.1
python3 -m pip install iqm-client==28.0.0
python3 -m pytest -v --durations=0 build/python/tests/interop/
pytest_status=$?
if [ ! $pytest_status -eq 0 ]; then
Expand Down Expand Up @@ -136,7 +136,7 @@ jobs:
# Rerun the MPI plugin test
cd $CUDAQ_REPO_ROOT
ctest --test-dir build -R MPIApiTest -V
external_plugin_status=$?
external_plugin_status=$?
if [ ! $external_plugin_status -eq 0 ] ; then
echo "::error file=test_in_devenv.yml::Test CUDA Quantum MPI Plugin Activation failed with status $external_plugin_status."
exit 1
Expand All @@ -153,7 +153,7 @@ jobs:
docker run --name cuda-quantum-dev cuda-quantum-dev:local
docker export cuda-quantum-dev > $output_directory/$filename.tar
docker rm -f cuda-quantum-dev
echo "filename=$filename" >> $GITHUB_OUTPUT
echo "output_directory=$output_directory" >> $GITHUB_OUTPUT
Expand Down Expand Up @@ -265,9 +265,9 @@ jobs:
if [ ! $pytest_status -eq 0 ] && [ ! $pytest_status -eq 5 ]; then
echo "::error file=test_in_devenv.yml::Python $backendTest tests failed with status $pytest_status."
exit 1
fi
done
fi
done
- name: Save environment
id: env_save
if: inputs.export_environment
Expand All @@ -279,7 +279,7 @@ jobs:
docker run --name dev_env dev_env:local
docker export dev_env > $output_directory/$filename.tar
docker rm -f dev_env
echo "filename=$filename" >> $GITHUB_OUTPUT
echo "output_directory=$output_directory" >> $GITHUB_OUTPUT
Expand Down
2 changes: 1 addition & 1 deletion docs/sphinx/targets/cpp/iqm.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Compile and run with:
// ```
// nvq++ --target iqm iqm.cpp --iqm-machine Crystal_5 -o out.x && ./out.x
// nvq++ --target iqm iqm.cpp -o out.x && ./out.x
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally, we try to make sure that changes are non-breaking (current API still works but gives a deprecated warning for some time before we remove it in favor of a different API). It would be good if we could have one test for python and one for C++ that checks the old API still works (possibly giving a warning or error if necessary with instructions for what should be used instead).

Copy link
Contributor Author

@iqm-bhoffmann iqm-bhoffmann Sep 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the architecture information is now fetched from the target machine (URL) giving it as parameter is no longer necessary and the parsing of the parameter was removed. From backward compatibility point nothing bad will happen if it is still given. It can however be confusing that this parameter is ignored and we can give a warning/information about this if desired.
Good point about a testcase for the behaviour if the parameter is still given. I will add such test.

// ```
// Assumes a valid set of credentials have been stored.

Expand Down
4 changes: 1 addition & 3 deletions docs/sphinx/targets/python/iqm.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@
# for every execution call on your kernel.
# To use different targets in the same file, you must update
# it via another call to `cudaq.set_target()`
cudaq.set_target("iqm",
url="http://localhost/cocos",
**{"qpu-architecture": "Crystal_5"})
cudaq.set_target("iqm", url="http://localhost/")

# Crystal_5 QPU architecture:
# QB1
Expand Down
113 changes: 113 additions & 0 deletions docs/sphinx/using/backends/hardware/backend_iqm.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
IQM Backend Advanced Use Cases
==============================

On this page advanced uses cases which are supported by the IQM backend integration are described.


Emulation Mode
++++++++++++++

.. tab:: Python

To emulate the IQM Server locally, without submitting to the IQM Server, you can set the ``emulate`` flag to ``True``.
This will emit any target specific compiler diagnostics, before running a noise free emulation.

.. code:: python
cudaq.set_target('iqm', emulate=True, url="https://<IQM Server>/")
Emulation mode will still contact the configured IQM Server to retrieve the dynamic quantum architecture resulting from the active calibration unless a QPU architecture file is explicitly specified.
This can be done by setting `mapping_file` to point to a file describing the QPU architecture which should be emulated.
If an architecture is specified no server URL is needed anymore.

.. code:: python
cudaq.set_target('iqm', emulate=True, mapping_file="<path+filename>")
The folder ``targettests/Target/IQM/`` contains sample QPU architecture files.
Find there files for the IQM Crystal architecture as well as files from real life QPUs which can be found on the IQM Resonance portal.

The QPU quantum architecture of a test with a real life IQM QPU can be saved for later use in emulation runs.
To do so the environment variable ``IQM_SAVE_QPU_QA`` must be set to point to a filename in addition to setting the URL of a Resonance server.
The test can even run as emulation as long as a server URL is given to retrieve the current dynamic quantum architecture from.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: let's remove from?


.. code:: bash
IQM_SERVER_URL="https://demo.qc.iqm.fi/" IQM_SAVE_QPU_QA="<path+filename for QPU architecture file>" python3 program.py
The file will be created with the given name. If the file already exists the test is aborted with an error.


.. tab:: C++

To emulate the IQM machine locally, without submitting to the IQM Server, you can pass the ``--emulate`` option to ``nvq++``.
This will emit any target specific compiler diagnostics, before running a noise free emulation.

.. code:: bash
nvq++ --target iqm --emulate src.cpp -o program
IQM_SERVER_URL="https://demo.qc.iqm.fi/" ./program
Emulation mode will still contact the configured IQM Server to retrieve the dynamic quantum architecture resulting from the active calibration unless a QPU architecture file is explicitly specified.
This can be done by specifying a file with the architecture either at compile time or in an variable in the environment executing the binary.
If an architecture is specified no server URL is needed anymore.

.. code:: bash
// With this binary multiple QPU architectures can be tested without recompilation.
nvq++ --target iqm --emulate src.cpp -o program
IQM_QPU_QA="<path+filename of QPU architecture file>" ./program
.. code:: bash
// This binary will use the given QPU architecture file until overwritten by environment variable "IQM_QPU_QA".
nvq++ --target iqm --emulate --mapping-file <path+filename of QPU architecture file> src.cpp -o program
./program
The folder ``targettests/Target/IQM/`` contains sample QPU architecture files.
Find there files for the IQM Crystal architecture as well as files from real life QPUs which can be found on the IQM Resonance portal.
The QPU architecture of a test with an IQM server can be saved for later use in emulation runs.
To do so the environment variable ``IQM_SAVE_QPU_QA`` must be set to point to a filename in addition to setting the URL of a Resonance server.
The test can even run as emulation as long as a server URL is given to retrieve the current dynamic quantum architecture from.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: let's remove from?

.. code:: bash
nvq++ --target iqm --emulate src.cpp -o program
IQM_SERVER_URL="https://demo.qc.iqm.fi/" IQM_SAVE_QPU_QA="<path+filename for QPU architecture file>" ./program
To see a complete example, take a look at :ref:`IQM examples <iqm-examples>`.
Setting the Number of Shots
+++++++++++++++++++++++++++
.. tab:: Python
The number of shots for a kernel execution can be set through
the ``shots_count`` argument to ``cudaq.sample`` or ``cudaq.observe``. By default,
the ``shots_count`` is set to 1000.
.. code:: python
cudaq.sample(kernel, shots_count=10000)
Using Credentials Saved in a File
+++++++++++++++++++++++++++++++++
The preferred way to pass the "API Token" to the IQM backend is through the environment variable ``IQM_TOKEN``. For compatibility the earlier used storage of the "API Token" in a file can still be used as follows:
The previously used ``IQM_TOKENS_FILE`` environment variable can still be used to point to a tokens file but will be ignored if the ``IQM_TOKEN`` variable is set.
The tokens file cannot be generated by the ``iqmclient`` tool anymore but can be created manually using the "API Token" obtained from the Resonance profile page.
A tokens file can be created and the environment variable set like this:
.. code:: bash
echo '{ "access_token": "<put-your-token-here>" }' > resonance-token.json
export IQM_TOKENS_FILE="path/to/resonance-token.json"
When storing the "API Token" in a file please make sure to restrict access to this file to only the account running tests.
No other user or group on the computer must have any access to this file.
93 changes: 39 additions & 54 deletions docs/sphinx/using/backends/hardware/superconducting.rst
Original file line number Diff line number Diff line change
Expand Up @@ -109,89 +109,74 @@ To see a complete example, take a look at :ref:`Anyon examples <anyon-examples>`


IQM
+++++++++
+++

.. _iqm-backend:

Support for submissions to IQM is currently under development.
In particular, two-qubit gates can only be performed on adjacent qubits. For more information, we refer to the respective hardware documentation.
Support for automatically injecting the necessary operations during compilation to execute arbitrary multi-qubit gates will be added in future versions.
`IQM Resonance <https://meetiqm.com/products/iqm-resonance/>`__ offers access to various different IQM quantum computers.
The machines available there will be constantly extended as development progresses.
Programmers of CUDA-Q may use IQM Resonance with either C++ or Python.

Setting Credentials
`````````````````````````
With this version it is no longer necessary to define the target QPU architecture in the code or at compile time.
The IQM backend integration now contacts at runtime the configured IQM server and fetches the active dynamic quantum architecture of the QPU.
This is then used as input to transpile the quantum kernel code just-in-time for the target QPU topology.
By setting the environment variable ``IQM_SERVER_URL`` the target server can be selected just before executing the program.
As result the python script or the compiled C++ program can be executed on different QPUs without recompilation or code changes.

Programmers of CUDA-Q may access the IQM Server from either C++ or Python. Following the `quick start guide <https://iqm-finland.github.io/cortex-cli/readme.html#using-cortex-cli>`__, install `iqm-cortex-cli` and login to initialize the tokens file.
The path to the tokens file can either be passed explicitly via an environment variable or it will be loaded automatically if located in
the default location :code:`~/.cache/iqm-cortex-cli/tokens.json`.
Please find also more documentation after logging in to the IQM Resonance portal.

.. code:: bash

export IQM_TOKENS_FILE="path/to/tokens.json"
Setting Credentials
```````````````````

Create a free account on the `IQM Resonance portal <https://meetiqm.com/products/iqm-resonance/>`__ and log-in.
Navigate to the account profile (top right). There generate an "API Token" and copy the generated token-string.
Set the environment variable ``IQM_TOKEN`` to contain the value of the token-string.
The IQM backend integration will use this as authorization token at the IQM server.



Submitting
`````````````````````````

.. tab:: Python

The target to which quantum kernels are submitted
can be controlled with the ``cudaq.set_target()`` function.
``````````

.. code:: python
.. tab:: Python

cudaq.set_target("iqm", url="https://<IQM Server>/cocos",**{"qpu-architecture": "Crystal_5"})
The target to which quantum kernels are submitted can be controlled with the ``cudaq.set_target()`` function.

To emulate the IQM Server locally, without submitting to the IQM Server,
you can also set the ``emulate`` flag to ``True``. This will emit any target
specific compiler diagnostics, before running a noise free emulation.
.. code:: python

.. code:: python
cudaq.set_target("iqm", url="https://<IQM Server>/")

cudaq.set_target('iqm', emulate=True)
Please note that setting the environment variable ``IQM_SERVER_URL`` takes precedence over the URL configured in the code.

The number of shots for a kernel execution can be set through
the ``shots_count`` argument to ``cudaq.sample`` or ``cudaq.observe``. By default,
the ``shots_count`` is set to 1000.

.. code:: python

cudaq.sample(kernel, shots_count=10000)

.. tab:: C++

To target quantum kernel code for execution on an IQM Server,
pass the ``--target iqm`` flag to the ``nvq++`` compiler, along with a specified ``--iqm-machine``.

.. note::
The ``--iqm-machine`` is a mandatory argument. This provided architecture must match
the device architecture that the program has been compiled against. The hardware architecture for a
specific IQM Server may be checked via `https://<IQM server>/cocos/quantum-architecture`.
To target quantum kernel code for execution on an IQM Server, pass the ``--target iqm`` option to the ``nvq++`` compiler.

.. code:: bash
.. code:: bash

nvq++ --target iqm --iqm-machine Crystal_5 src.cpp
nvq++ --target iqm src.cpp

Once the binary for a specific IQM QPU architecture is compiled, it can be executed against any IQM Server with the same QPU architecture:
Once the binary for an IQM QPU is compiled, it can be executed against any IQM Server by setting the environment variable ``IQM_SERVER_URL`` as shown here:

.. code:: bash
.. code:: bash

nvq++ --target iqm --iqm-machine Crystal_5 src.cpp -o program
IQM_SERVER_URL="https://demo.qc.iqm.fi/cocos" ./program
nvq++ --target iqm src.cpp -o program
IQM_SERVER_URL="https://demo.qc.iqm.fi/" ./program

# Executing the same program against an IQM Server with a different underlying QPU
# architecture will result in an error.
IQM_SERVER_URL="https://<Crystal_20 IQM Server>/cocos" ./program

To emulate the IQM machine locally, without submitting to the IQM Server,
you can also pass the ``--emulate`` flag to ``nvq++``. This will emit any target
specific compiler diagnostics, before running a noise free emulation.
To see a complete example for using IQM server backends, take a look at :ref:`IQM examples <iqm-examples>`.

.. code:: bash

nvq++ --emulate --target iqm --iqm-machine Crystal_5 src.cpp
Advanced use cases
``````````````````

The IQM backend integration offers more options for advanced use cases. Please find these here:

.. toctree::
:maxdepth: 2

To see a complete example, take a look at :ref:`IQM examples <iqm-examples>`.
IQM backend advanced use cases <backend_iqm.rst>


OQC
Expand Down
7 changes: 4 additions & 3 deletions lib/Optimizer/CodeGen/TranslateToIQMJson.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright (c) 2022 - 2025 NVIDIA Corporation & Affiliates. *
* All rights reserved. *
* Copyright 2025 IQM Quantum Computers *
* *
* This source code and the accompanying materials are made available under *
* the terms of the Apache License 2.0 which accompanies this distribution. *
Expand Down Expand Up @@ -121,10 +122,10 @@ static LogicalResult emitOperation(nlohmann::json &json,
emitter.getOrAssignName(optor->getResult(1),
emitter.getOrAssignName(optor.getTarget(0)).str());
} else {
json["name"] = name;
json["name"] = "prx";

if (optor.getParameters().size() != 2)
optor.emitError("IQM phased_rx gate expects exactly two parameters.");
optor.emitError("IQM prx gate expects exactly two parameters.");

auto parameter0 =
cudaq::getParameterValueAsDouble(optor.getParameters()[0]);
Expand Down Expand Up @@ -154,7 +155,7 @@ static LogicalResult emitOperation(nlohmann::json &json,

static LogicalResult emitOperation(nlohmann::json &json,
cudaq::Emitter &emitter, quake::MzOp op) {
json["name"] = "measurement";
json["name"] = "measure";
std::vector<std::string> qubits;
for (auto target : op.getTargets())
qubits.push_back(emitter.getOrAssignName(target).str());
Expand Down
Loading