Skip to content

Commit b66c5bb

Browse files
iqm-bhoffmannsacpisbettinaheim
committed
Support dynamic quantum architecture for IQM QPUs (#3298)
* Support dynamic quantum architecture for IQM QPUs For IQM machines fetch the quantum architecture from server, derive the dynamic architecture from this and write it to an architecture file. This file is then passed in the lowering pipeline in place of the previously used static architecture files. The output from the algorithm for finding usable qubits generates a list of qubits which are calibrated for mz, cz and prx. A mapping ensures that qubit names are enumerated in a linear manner and not fully calibrated qubits do not show in the architecture file. The architecture file is created in the system temp directory with a unique filename and deleted after the job has been sent to the IQM server. Changes in function * Removed parameter "--iqm-machine" which was used to specify the IQM quantum architecture at compile time. * Removed static architecture files provided for Adonis, Apollo, and Aphrodite architectures. * Removed machine architecture bindings from IQM tests. * Implemented getting the authorization token from IQM_TOKEN environment variable. If this is not set the previous mechanism reading the token from a JSON file is used. * Updated IQM JSON output of LLVM to latest syntax. "phased_rx" -> "prx", "measurement" -> "measure" in both emitter code and tests. Test related changes * Adapted IQM mock server to latest iqmclient API version (v28.0.0) and IQM server API changes. * Implemented in IQM mock server the 20 qubit Apollo quantum architecture. * Added support for mapping of qubits syntax in the job request to the mock server. * In the mock server deliberately removed QB2 and QB3 from the list of PRX calibrated gates. This results in changes in the topology and forces the CUDA-Q code to work with an imperfect calibrated system. This tests the implemented algorithm with every testcase which uses more than 1 qubit. * In mock server implemented a full checking of gates used in circuits versus the topology to verify that all 2 qubit gates are supported by the mock qpu. * Pass the authorization token to IQM mock server with env-variable. This includes also a new testcase addressing the IQM_TOKEN environment variable. * Save and restore environment variables for testcases modifying them. So the order of testcases does not matter anymore. * Fixed evaluation of 2 qubit testcases which failed on some simulations. Documentation * Updated the IQM parts of the documentation and examples. Explained changes from previous version and removed references to the no longer needed machine names. * Cleanup: improved doxygen headers and few other comments. * Cleanup: Added copyright to touched files Addresses issues: #1589, #865 --------- Signed-off-by: Bernd Hoffmann <[email protected]> Signed-off-by: iqm-bhoffmann <[email protected]> * removing yapf as spell checker is complaining about it Signed-off-by: Sachin Pisal <[email protected]> * Removed debug prints which are failing Commented out debug output dumping JSON data. The code worked earlier but now fails compilation reporting a type issue. Signed-off-by: Bernd Hoffmann <[email protected]> * Removed commented-out debug prints entirely Instead of fixing a formatting error removed some debug prints entirely as they are just details of a more general previous printout. Signed-off-by: Bernd Hoffmann <[email protected]> * Fixed emulation mode for IQM server Fixed implementation of --emulate parameter. Previously it tried load the dynamic quantum architecture from server despite "emulate" means without server. This caused several ctests to fail. Removed the --iqm-machine parameter from all ctest lines in the various C++ test programs. Adapted the ctests mapping testcase to use a Crystal_5.txt file and restored this to the project. Signed-off-by: Bernd Hoffmann <[email protected]> * Fixed mapping file issue for emulation mode In emulation mode provide a mapping file for the 20 qubit crystal architecture. Restored the Crystal_20.txt (former Apollo.txt) mapping file. This is used only in emulation mode. Added header file <unistd.h> which was missing in IQMServerHelper. Signed-off-by: Bernd Hoffmann <[email protected]> * Corrected comments and code readability After feedback in internal review corrected: - Wording of some comments. - Improved writing of the bit encoded flag variable. Only for readability - non functional change. - Removed an unused include. Signed-off-by: Bernd Hoffmann <[email protected]> * Correction from clang-format Signed-off-by: Bernd Hoffmann <[email protected]> * Remove again `prx` from spellchecker whitelist Signed-off-by: Bernd Hoffmann <[email protected]> * Clarified documentation Review feedback: Removed outdated paragraph. Fixed typo in example. Signed-off-by: Bernd Hoffmann <[email protected]> * Alternate ways to define the IQM QPU architecture Allow defining the IQM QPU architecture at runtime via environment variable IQM_QPU_QA. The value of this variable is interpreted as a path+filename of an QPU architecture (mapping) file. Aternatively the IQM QPU archtecture can be given at compile time with parameter "--mapping-file" to the nvq++ or in the backend-string as "mapping_file". Moved the IQM QPU architecture files from "runtime" into the "targettest" folder. Added file for the IQM Crystal-54 architecture. Changed the lit variable pointing to these folders. Updated all testcases testing IQM target which use "--emulate" to use QPU architecture via environment variable. Signed-off-by: Bernd Hoffmann <[email protected]> * Updated IQM doc, save DQA to file, tests Updated the IQM backend documentation. Created a new subpage there to explain some advanced use-cases. Added a way to save the dynamic quantum architecture of a server to file for later use. Added example files of a quantum architecture to targettests/Target/IQM/ folder. Added testcase to unittests testing the options to load and save a dynamic quantum architecture to file. Signed-off-by: Bernd Hoffmann <[email protected]> * Fixup lint and linkcheck issues The link to Resonance is valid but only when requested with an accept string of "text/html" a response with 200 will be returned. Reverted to previously page instead. Signed-off-by: Bernd Hoffmann <[email protected]> --------- Signed-off-by: Bernd Hoffmann <[email protected]> Signed-off-by: iqm-bhoffmann <[email protected]> Signed-off-by: Sachin Pisal <[email protected]> Co-authored-by: Sachin Pisal <[email protected]> Co-authored-by: Bettina Heim <[email protected]>
1 parent 4dd9969 commit b66c5bb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+1051
-471
lines changed

.github/workflows/config/spelling_allowlist.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,7 @@ toolchain
354354
toolchains
355355
toolset
356356
transmon
357+
transpile
357358
trotterization
358359
uccsd
359360
unary

.github/workflows/integration_tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -636,7 +636,7 @@ jobs:
636636
;;
637637
638638
iqm)
639-
nvq++ -DSYNTAX_CHECK --target iqm --iqm-machine Crystal_5 $filename
639+
nvq++ -DSYNTAX_CHECK --target iqm $filename
640640
test_status=$?
641641
if [ $test_status -eq 0 ]; then
642642
./a.out

.github/workflows/test_in_devenv.yml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ jobs:
9191
shell: bash
9292
run: |
9393
cd $CUDAQ_REPO_ROOT
94-
python3 -m pip install iqm-client==16.1
94+
python3 -m pip install iqm-client==28.0.0
9595
python3 -m pytest -v --durations=0 build/python/tests/interop/
9696
pytest_status=$?
9797
if [ ! $pytest_status -eq 0 ]; then
@@ -136,7 +136,7 @@ jobs:
136136
# Rerun the MPI plugin test
137137
cd $CUDAQ_REPO_ROOT
138138
ctest --test-dir build -R MPIApiTest -V
139-
external_plugin_status=$?
139+
external_plugin_status=$?
140140
if [ ! $external_plugin_status -eq 0 ] ; then
141141
echo "::error file=test_in_devenv.yml::Test CUDA Quantum MPI Plugin Activation failed with status $external_plugin_status."
142142
exit 1
@@ -153,7 +153,7 @@ jobs:
153153
docker run --name cuda-quantum-dev cuda-quantum-dev:local
154154
docker export cuda-quantum-dev > $output_directory/$filename.tar
155155
docker rm -f cuda-quantum-dev
156-
156+
157157
echo "filename=$filename" >> $GITHUB_OUTPUT
158158
echo "output_directory=$output_directory" >> $GITHUB_OUTPUT
159159
@@ -265,9 +265,9 @@ jobs:
265265
if [ ! $pytest_status -eq 0 ] && [ ! $pytest_status -eq 5 ]; then
266266
echo "::error file=test_in_devenv.yml::Python $backendTest tests failed with status $pytest_status."
267267
exit 1
268-
fi
269-
done
270-
268+
fi
269+
done
270+
271271
- name: Save environment
272272
id: env_save
273273
if: inputs.export_environment
@@ -279,7 +279,7 @@ jobs:
279279
docker run --name dev_env dev_env:local
280280
docker export dev_env > $output_directory/$filename.tar
281281
docker rm -f dev_env
282-
282+
283283
echo "filename=$filename" >> $GITHUB_OUTPUT
284284
echo "output_directory=$output_directory" >> $GITHUB_OUTPUT
285285

docs/sphinx/targets/cpp/iqm.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Compile and run with:
22
// ```
3-
// nvq++ --target iqm iqm.cpp --iqm-machine Crystal_5 -o out.x && ./out.x
3+
// nvq++ --target iqm iqm.cpp -o out.x && ./out.x
44
// ```
55
// Assumes a valid set of credentials have been stored.
66

docs/sphinx/targets/python/iqm.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@
44
# for every execution call on your kernel.
55
# To use different targets in the same file, you must update
66
# it via another call to `cudaq.set_target()`
7-
cudaq.set_target("iqm",
8-
url="http://localhost/cocos",
9-
**{"qpu-architecture": "Crystal_5"})
7+
cudaq.set_target("iqm", url="http://localhost/")
108

119
# Crystal_5 QPU architecture:
1210
# QB1
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
IQM Backend Advanced Use Cases
2+
==============================
3+
4+
On this page advanced uses cases which are supported by the IQM backend integration are described.
5+
6+
7+
Emulation Mode
8+
++++++++++++++
9+
10+
.. tab:: Python
11+
12+
To emulate the IQM Server locally, without submitting to the IQM Server, you can set the ``emulate`` flag to ``True``.
13+
This will emit any target specific compiler diagnostics, before running a noise free emulation.
14+
15+
.. code:: python
16+
17+
cudaq.set_target('iqm', emulate=True, url="https://<IQM Server>/")
18+
19+
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.
20+
This can be done by setting `mapping_file` to point to a file describing the QPU architecture which should be emulated.
21+
If an architecture is specified no server URL is needed anymore.
22+
23+
.. code:: python
24+
25+
cudaq.set_target('iqm', emulate=True, mapping_file="<path+filename>")
26+
27+
The folder ``targettests/Target/IQM/`` contains sample QPU architecture files.
28+
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.
29+
30+
The QPU quantum architecture of a test with a real life IQM QPU can be saved for later use in emulation runs.
31+
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.
32+
The test can even run as emulation as long as a server URL is given to retrieve the current dynamic quantum architecture from.
33+
34+
.. code:: bash
35+
36+
IQM_SERVER_URL="https://demo.qc.iqm.fi/" IQM_SAVE_QPU_QA="<path+filename for QPU architecture file>" python3 program.py
37+
38+
39+
The file will be created with the given name. If the file already exists the test is aborted with an error.
40+
41+
42+
.. tab:: C++
43+
44+
To emulate the IQM machine locally, without submitting to the IQM Server, you can pass the ``--emulate`` option to ``nvq++``.
45+
This will emit any target specific compiler diagnostics, before running a noise free emulation.
46+
47+
.. code:: bash
48+
49+
nvq++ --target iqm --emulate src.cpp -o program
50+
IQM_SERVER_URL="https://demo.qc.iqm.fi/" ./program
51+
52+
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.
53+
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.
54+
If an architecture is specified no server URL is needed anymore.
55+
56+
.. code:: bash
57+
58+
// With this binary multiple QPU architectures can be tested without recompilation.
59+
nvq++ --target iqm --emulate src.cpp -o program
60+
IQM_QPU_QA="<path+filename of QPU architecture file>" ./program
61+
62+
.. code:: bash
63+
64+
// This binary will use the given QPU architecture file until overwritten by environment variable "IQM_QPU_QA".
65+
nvq++ --target iqm --emulate --mapping-file <path+filename of QPU architecture file> src.cpp -o program
66+
./program
67+
68+
The folder ``targettests/Target/IQM/`` contains sample QPU architecture files.
69+
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.
70+
71+
The QPU architecture of a test with an IQM server can be saved for later use in emulation runs.
72+
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.
73+
The test can even run as emulation as long as a server URL is given to retrieve the current dynamic quantum architecture from.
74+
75+
.. code:: bash
76+
77+
nvq++ --target iqm --emulate src.cpp -o program
78+
IQM_SERVER_URL="https://demo.qc.iqm.fi/" IQM_SAVE_QPU_QA="<path+filename for QPU architecture file>" ./program
79+
80+
81+
To see a complete example, take a look at :ref:`IQM examples <iqm-examples>`.
82+
83+
84+
Setting the Number of Shots
85+
+++++++++++++++++++++++++++
86+
87+
.. tab:: Python
88+
89+
The number of shots for a kernel execution can be set through
90+
the ``shots_count`` argument to ``cudaq.sample`` or ``cudaq.observe``. By default,
91+
the ``shots_count`` is set to 1000.
92+
93+
.. code:: python
94+
95+
cudaq.sample(kernel, shots_count=10000)
96+
97+
98+
Using Credentials Saved in a File
99+
+++++++++++++++++++++++++++++++++
100+
101+
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:
102+
103+
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.
104+
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.
105+
A tokens file can be created and the environment variable set like this:
106+
107+
.. code:: bash
108+
109+
echo '{ "access_token": "<put-your-token-here>" }' > resonance-token.json
110+
export IQM_TOKENS_FILE="path/to/resonance-token.json"
111+
112+
When storing the "API Token" in a file please make sure to restrict access to this file to only the account running tests.
113+
No other user or group on the computer must have any access to this file.

docs/sphinx/using/backends/hardware/superconducting.rst

Lines changed: 39 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -109,89 +109,74 @@ To see a complete example, take a look at :ref:`Anyon examples <anyon-examples>`
109109

110110

111111
IQM
112-
+++++++++
112+
+++
113113

114114
.. _iqm-backend:
115115

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

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

123-
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.
124-
The path to the tokens file can either be passed explicitly via an environment variable or it will be loaded automatically if located in
125-
the default location :code:`~/.cache/iqm-cortex-cli/tokens.json`.
126+
Please find also more documentation after logging in to the IQM Resonance portal.
126127

127-
.. code:: bash
128128

129-
export IQM_TOKENS_FILE="path/to/tokens.json"
129+
Setting Credentials
130+
```````````````````
131+
132+
Create a free account on the `IQM Resonance portal <https://meetiqm.com/products/iqm-resonance/>`__ and log-in.
133+
Navigate to the account profile (top right). There generate an "API Token" and copy the generated token-string.
134+
Set the environment variable ``IQM_TOKEN`` to contain the value of the token-string.
135+
The IQM backend integration will use this as authorization token at the IQM server.
130136

131137

132-
133138
Submitting
134-
`````````````````````````
135-
136-
.. tab:: Python
137-
138-
The target to which quantum kernels are submitted
139-
can be controlled with the ``cudaq.set_target()`` function.
139+
``````````
140140

141-
.. code:: python
141+
.. tab:: Python
142142

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

145-
To emulate the IQM Server locally, without submitting to the IQM Server,
146-
you can also set the ``emulate`` flag to ``True``. This will emit any target
147-
specific compiler diagnostics, before running a noise free emulation.
145+
.. code:: python
148146
149-
.. code:: python
147+
cudaq.set_target("iqm", url="https://<IQM Server>/")
150148
151-
cudaq.set_target('iqm', emulate=True)
149+
Please note that setting the environment variable ``IQM_SERVER_URL`` takes precedence over the URL configured in the code.
152150

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

157-
.. code:: python
158-
159-
cudaq.sample(kernel, shots_count=10000)
160-
161152
.. tab:: C++
162-
163-
To target quantum kernel code for execution on an IQM Server,
164-
pass the ``--target iqm`` flag to the ``nvq++`` compiler, along with a specified ``--iqm-machine``.
165153

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

171-
.. code:: bash
156+
.. code:: bash
172157
173-
nvq++ --target iqm --iqm-machine Crystal_5 src.cpp
158+
nvq++ --target iqm src.cpp
174159
175-
Once the binary for a specific IQM QPU architecture is compiled, it can be executed against any IQM Server with the same QPU architecture:
160+
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:
176161

177-
.. code:: bash
162+
.. code:: bash
178163
179-
nvq++ --target iqm --iqm-machine Crystal_5 src.cpp -o program
180-
IQM_SERVER_URL="https://demo.qc.iqm.fi/cocos" ./program
164+
nvq++ --target iqm src.cpp -o program
165+
IQM_SERVER_URL="https://demo.qc.iqm.fi/" ./program
181166
182-
# Executing the same program against an IQM Server with a different underlying QPU
183-
# architecture will result in an error.
184-
IQM_SERVER_URL="https://<Crystal_20 IQM Server>/cocos" ./program
185167
186-
To emulate the IQM machine locally, without submitting to the IQM Server,
187-
you can also pass the ``--emulate`` flag to ``nvq++``. This will emit any target
188-
specific compiler diagnostics, before running a noise free emulation.
168+
To see a complete example for using IQM server backends, take a look at :ref:`IQM examples <iqm-examples>`.
189169

190-
.. code:: bash
191170

192-
nvq++ --emulate --target iqm --iqm-machine Crystal_5 src.cpp
171+
Advanced use cases
172+
``````````````````
173+
174+
The IQM backend integration offers more options for advanced use cases. Please find these here:
175+
176+
.. toctree::
177+
:maxdepth: 2
193178

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

196181

197182
OQC

lib/Optimizer/CodeGen/TranslateToIQMJson.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/*******************************************************************************
22
* Copyright (c) 2022 - 2025 NVIDIA Corporation & Affiliates. *
33
* All rights reserved. *
4+
* Copyright 2025 IQM Quantum Computers *
45
* *
56
* This source code and the accompanying materials are made available under *
67
* the terms of the Apache License 2.0 which accompanies this distribution. *
@@ -121,10 +122,10 @@ static LogicalResult emitOperation(nlohmann::json &json,
121122
emitter.getOrAssignName(optor->getResult(1),
122123
emitter.getOrAssignName(optor.getTarget(0)).str());
123124
} else {
124-
json["name"] = name;
125+
json["name"] = "prx";
125126

126127
if (optor.getParameters().size() != 2)
127-
optor.emitError("IQM phased_rx gate expects exactly two parameters.");
128+
optor.emitError("IQM prx gate expects exactly two parameters.");
128129

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

155156
static LogicalResult emitOperation(nlohmann::json &json,
156157
cudaq::Emitter &emitter, quake::MzOp op) {
157-
json["name"] = "measurement";
158+
json["name"] = "measure";
158159
std::vector<std::string> qubits;
159160
for (auto target : op.getTargets())
160161
qubits.push_back(emitter.getOrAssignName(target).str());

0 commit comments

Comments
 (0)