iqm-pulla 11.1.0__py3-none-any.whl → 11.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- iqm/pulla/pulla.py +113 -53
- {iqm_pulla-11.1.0.dist-info → iqm_pulla-11.3.0.dist-info}/METADATA +6 -6
- {iqm_pulla-11.1.0.dist-info → iqm_pulla-11.3.0.dist-info}/RECORD +7 -7
- {iqm_pulla-11.1.0.dist-info → iqm_pulla-11.3.0.dist-info}/AUTHORS.rst +0 -0
- {iqm_pulla-11.1.0.dist-info → iqm_pulla-11.3.0.dist-info}/LICENSE.txt +0 -0
- {iqm_pulla-11.1.0.dist-info → iqm_pulla-11.3.0.dist-info}/WHEEL +0 -0
- {iqm_pulla-11.1.0.dist-info → iqm_pulla-11.3.0.dist-info}/top_level.txt +0 -0
iqm/pulla/pulla.py
CHANGED
|
@@ -210,6 +210,7 @@ class Pulla:
|
|
|
210
210
|
context: dict[str, Any],
|
|
211
211
|
settings: SettingNode,
|
|
212
212
|
verbose: bool = True,
|
|
213
|
+
wait_completion: bool = True,
|
|
213
214
|
) -> StationControlResult:
|
|
214
215
|
"""Executes a quantum circuit on the remote quantum computer.
|
|
215
216
|
|
|
@@ -218,6 +219,7 @@ class Pulla:
|
|
|
218
219
|
context: Context object of the successful compiler run, containing the readout mappings.
|
|
219
220
|
settings: Station settings.
|
|
220
221
|
verbose: Whether to print results.
|
|
222
|
+
wait_completion: If True, returns immediately with job ID. If False, waits for completion.
|
|
221
223
|
|
|
222
224
|
Returns:
|
|
223
225
|
results of the execution
|
|
@@ -240,72 +242,130 @@ class Pulla:
|
|
|
240
242
|
)
|
|
241
243
|
)
|
|
242
244
|
job_id = uuid.UUID(sweep_response["job_id"])
|
|
243
|
-
try:
|
|
244
|
-
logger.info("Created job in queue with ID: %s", job_id)
|
|
245
|
-
if href := sweep_response.get("job_href"):
|
|
246
|
-
logger.info("Job link: %s", href)
|
|
247
245
|
|
|
248
|
-
|
|
246
|
+
logger.info("Created job in queue with ID: %s", job_id)
|
|
247
|
+
if href := sweep_response.get("job_href"):
|
|
248
|
+
logger.info("Job link: %s", href)
|
|
249
249
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
250
|
+
if wait_completion:
|
|
251
|
+
return self.get_execution_result(job_id, context, verbose, wait_completion=True)
|
|
252
|
+
else:
|
|
253
|
+
return StationControlResult(sweep_id=job_id, task_id=job_id, status=TaskStatus.PENDING)
|
|
253
254
|
|
|
254
|
-
|
|
255
|
-
|
|
255
|
+
def get_execution_result(
|
|
256
|
+
self,
|
|
257
|
+
job_id: uuid.UUID,
|
|
258
|
+
context: dict[str, Any],
|
|
259
|
+
verbose: bool = True,
|
|
260
|
+
wait_completion: bool = True,
|
|
261
|
+
) -> StationControlResult:
|
|
262
|
+
"""Get execution results.
|
|
256
263
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
sweep_data = self._station_control.get_sweep(job_id)
|
|
263
|
-
if job_data.job_status == JobExecutorStatus.READY:
|
|
264
|
-
logger.info("Sweep status: %s", str(sweep_data.job_status))
|
|
265
|
-
|
|
266
|
-
sc_result.status = TaskStatus.READY
|
|
267
|
-
sc_result.result = map_sweep_results_to_logical_qubits(
|
|
268
|
-
self._station_control.get_sweep_results(job_id),
|
|
269
|
-
context["readout_mappings"],
|
|
270
|
-
context["options"].heralding_mode,
|
|
271
|
-
)
|
|
272
|
-
sc_result.start_time = (
|
|
273
|
-
sweep_data.begin_timestamp.isoformat() if sweep_data.begin_timestamp else None
|
|
274
|
-
)
|
|
275
|
-
sc_result.end_time = sweep_data.end_timestamp.isoformat() if sweep_data.end_timestamp else None
|
|
264
|
+
Args:
|
|
265
|
+
job_id: The ID of the job to process.
|
|
266
|
+
context: Context object of the successful compiler run, containing the readout mappings.
|
|
267
|
+
verbose: Whether to print results.
|
|
268
|
+
wait_completion: If True, waits for job completion. If False, returns current status.
|
|
276
269
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
logger.info(sc_result.result)
|
|
270
|
+
Returns:
|
|
271
|
+
The processed station control result.
|
|
280
272
|
|
|
281
|
-
|
|
273
|
+
"""
|
|
274
|
+
sc_result = StationControlResult(sweep_id=job_id, task_id=job_id, status=TaskStatus.PENDING)
|
|
282
275
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
sweep_data.begin_timestamp.isoformat() if sweep_data.begin_timestamp else None
|
|
287
|
-
)
|
|
288
|
-
sc_result.end_time = sweep_data.end_timestamp.isoformat() if sweep_data.end_timestamp else None
|
|
289
|
-
sc_result.message = str(job_data.job_error)
|
|
290
|
-
logger.error("Submission failed! Error: %s", sc_result.message)
|
|
291
|
-
return sc_result
|
|
276
|
+
try:
|
|
277
|
+
if wait_completion:
|
|
278
|
+
logger.info("Waiting for the job to finish...")
|
|
292
279
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
280
|
+
while True:
|
|
281
|
+
job_data = self._station_control.get_job(job_id)
|
|
282
|
+
sc_result.status = TaskStatus.PENDING
|
|
283
|
+
|
|
284
|
+
if job_data.job_status <= JobExecutorStatus.EXECUTION_STARTED: # type: ignore[operator]
|
|
285
|
+
if wait_completion:
|
|
286
|
+
# Wait in the task queue while showing a progress bar
|
|
287
|
+
interrupted = self._station_control._wait_job_completion( # type: ignore[attr-defined]
|
|
288
|
+
str(job_id), get_progress_bar_callback()
|
|
289
|
+
)
|
|
290
|
+
if interrupted:
|
|
291
|
+
raise KeyboardInterrupt
|
|
292
|
+
else:
|
|
293
|
+
# Non-blocking check - return current status
|
|
294
|
+
sc_result.status = (
|
|
295
|
+
TaskStatus.PROGRESS
|
|
296
|
+
if job_data.job_status == JobExecutorStatus.EXECUTION_STARTED
|
|
297
|
+
else TaskStatus.PENDING
|
|
297
298
|
)
|
|
298
|
-
sc_result.end_time = sweep_data.end_timestamp.isoformat() if sweep_data.end_timestamp else None
|
|
299
|
-
sc_result.message = str(job_data.job_error)
|
|
300
|
-
logger.error("Submission was revoked!")
|
|
301
299
|
return sc_result
|
|
302
|
-
|
|
303
|
-
|
|
300
|
+
else:
|
|
301
|
+
# job is not in queue or executing, so we can query the sweep
|
|
302
|
+
result_or_nothing = self._get_result_of_started_job(
|
|
303
|
+
context, job_data, job_id, sc_result, wait_completion, verbose
|
|
304
|
+
)
|
|
305
|
+
if result_or_nothing is not None:
|
|
306
|
+
return result_or_nothing
|
|
307
|
+
|
|
308
|
+
if wait_completion:
|
|
309
|
+
time.sleep(1)
|
|
310
|
+
else:
|
|
311
|
+
break
|
|
304
312
|
|
|
305
313
|
except KeyboardInterrupt as exc:
|
|
306
|
-
|
|
307
|
-
|
|
314
|
+
if wait_completion:
|
|
315
|
+
logger.info("Caught KeyboardInterrupt, revoking job %s", job_id)
|
|
316
|
+
self._station_control.abort_job(job_id)
|
|
308
317
|
raise KeyboardInterrupt from exc
|
|
309
318
|
|
|
319
|
+
return sc_result
|
|
320
|
+
|
|
321
|
+
def _get_result_of_started_job(
|
|
322
|
+
self,
|
|
323
|
+
context: dict[str, Any],
|
|
324
|
+
job_data: Any,
|
|
325
|
+
job_id: uuid.UUID,
|
|
326
|
+
sc_result: StationControlResult,
|
|
327
|
+
wait_completion: bool,
|
|
328
|
+
verbose: bool,
|
|
329
|
+
) -> StationControlResult | None:
|
|
330
|
+
sweep_data = self._station_control.get_sweep(job_id)
|
|
331
|
+
if job_data.job_status == JobExecutorStatus.READY:
|
|
332
|
+
if wait_completion:
|
|
333
|
+
logger.info("Sweep status: %s", str(sweep_data.job_status))
|
|
334
|
+
|
|
335
|
+
sc_result.status = TaskStatus.READY
|
|
336
|
+
sc_result.result = map_sweep_results_to_logical_qubits(
|
|
337
|
+
self._station_control.get_sweep_results(job_id),
|
|
338
|
+
context["readout_mappings"],
|
|
339
|
+
context["options"].heralding_mode,
|
|
340
|
+
)
|
|
341
|
+
sc_result.start_time = sweep_data.begin_timestamp.isoformat() if sweep_data.begin_timestamp else None
|
|
342
|
+
sc_result.end_time = sweep_data.end_timestamp.isoformat() if sweep_data.end_timestamp else None
|
|
343
|
+
|
|
344
|
+
if verbose and wait_completion:
|
|
345
|
+
# TODO: Consider using just 'logger.debug' here and remove 'verbose'
|
|
346
|
+
logger.info(sc_result.result)
|
|
347
|
+
|
|
348
|
+
return sc_result
|
|
349
|
+
|
|
350
|
+
if job_data.job_status == JobExecutorStatus.FAILED:
|
|
351
|
+
sc_result.status = TaskStatus.FAILED
|
|
352
|
+
sc_result.start_time = sweep_data.begin_timestamp.isoformat() if sweep_data.begin_timestamp else None
|
|
353
|
+
sc_result.end_time = sweep_data.end_timestamp.isoformat() if sweep_data.end_timestamp else None
|
|
354
|
+
sc_result.message = str(job_data.job_error)
|
|
355
|
+
if wait_completion:
|
|
356
|
+
logger.error("Submission failed! Error: %s", sc_result.message)
|
|
357
|
+
return sc_result
|
|
358
|
+
|
|
359
|
+
if job_data.job_status == JobExecutorStatus.ABORTED:
|
|
360
|
+
sc_result.status = TaskStatus.FAILED
|
|
361
|
+
sc_result.start_time = sweep_data.begin_timestamp.isoformat() if sweep_data.begin_timestamp else None
|
|
362
|
+
sc_result.end_time = sweep_data.end_timestamp.isoformat() if sweep_data.end_timestamp else None
|
|
363
|
+
sc_result.message = str(job_data.job_error)
|
|
364
|
+
if wait_completion:
|
|
365
|
+
logger.error("Submission was revoked!")
|
|
366
|
+
return sc_result
|
|
367
|
+
|
|
368
|
+
return None
|
|
369
|
+
|
|
310
370
|
|
|
311
371
|
init_loggers({"iqm": "INFO"})
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: iqm-pulla
|
|
3
|
-
Version: 11.
|
|
3
|
+
Version: 11.3.0
|
|
4
4
|
Summary: Client library for pulse-level access to an IQM quantum computer
|
|
5
5
|
Author-email: IQM Finland Oy <developers@meetiqm.com>
|
|
6
6
|
License: Apache License
|
|
@@ -217,30 +217,30 @@ Description-Content-Type: text/x-rst
|
|
|
217
217
|
License-File: LICENSE.txt
|
|
218
218
|
License-File: AUTHORS.rst
|
|
219
219
|
Requires-Dist: iqm-exa-common <27,>=26
|
|
220
|
-
Requires-Dist: iqm-station-control-client <10
|
|
220
|
+
Requires-Dist: iqm-station-control-client <11,>=10
|
|
221
221
|
Requires-Dist: iqm-pulse <13,>=12
|
|
222
222
|
Requires-Dist: iqm-data-definitions <3.0,>=2.13
|
|
223
223
|
Requires-Dist: pylatexenc ==2.10
|
|
224
224
|
Requires-Dist: pydantic <3.0,>=2.10.4
|
|
225
225
|
Provides-Extra: notebook
|
|
226
226
|
Requires-Dist: iqm-exa-common <27,>=26 ; extra == 'notebook'
|
|
227
|
-
Requires-Dist: iqm-station-control-client <10
|
|
227
|
+
Requires-Dist: iqm-station-control-client <11,>=10 ; extra == 'notebook'
|
|
228
228
|
Requires-Dist: iqm-pulse <13,>=12 ; extra == 'notebook'
|
|
229
229
|
Requires-Dist: notebook <7,>=6.4.11 ; extra == 'notebook'
|
|
230
230
|
Requires-Dist: matplotlib <4,>=3.6.3 ; extra == 'notebook'
|
|
231
231
|
Requires-Dist: nbclient ~=0.5.10 ; extra == 'notebook'
|
|
232
232
|
Provides-Extra: qir
|
|
233
233
|
Requires-Dist: iqm-exa-common <27,>=26 ; extra == 'qir'
|
|
234
|
-
Requires-Dist: iqm-station-control-client <10
|
|
234
|
+
Requires-Dist: iqm-station-control-client <11,>=10 ; extra == 'qir'
|
|
235
235
|
Requires-Dist: iqm-pulse <13,>=12 ; extra == 'qir'
|
|
236
236
|
Requires-Dist: iqm-pyqir ==0.12.0 ; extra == 'qir'
|
|
237
237
|
Requires-Dist: iqm-qiskit-qir ==0.8.0 ; extra == 'qir'
|
|
238
238
|
Provides-Extra: qiskit
|
|
239
239
|
Requires-Dist: iqm-exa-common <27,>=26 ; extra == 'qiskit'
|
|
240
|
-
Requires-Dist: iqm-station-control-client <10
|
|
240
|
+
Requires-Dist: iqm-station-control-client <11,>=10 ; extra == 'qiskit'
|
|
241
241
|
Requires-Dist: iqm-pulse <13,>=12 ; extra == 'qiskit'
|
|
242
|
-
Requires-Dist: iqm-client <32,>=31 ; extra == 'qiskit'
|
|
243
242
|
Requires-Dist: iqm-client[qiskit] <32,>=31 ; extra == 'qiskit'
|
|
243
|
+
Requires-Dist: iqm-client <32,>=31 ; extra == 'qiskit'
|
|
244
244
|
|
|
245
245
|
IQM Pulla
|
|
246
246
|
#########
|
|
@@ -11,7 +11,7 @@ iqm/cpc/interface/compiler.py,sha256=zxUyalyiBIQA9EUK_fDGNq0SZ5OwfxQdB6Xk5BDDMVk
|
|
|
11
11
|
iqm/pulla/__init__.py,sha256=fj5Qh8R9K-z6q5g9-CySBZsG8d33nU7hCHrqIIB8_-0,901
|
|
12
12
|
iqm/pulla/calibration.py,sha256=c_SNlTxXC0y-ahDY7JY53N7SofU5WUWMrNBogtdfHl4,4523
|
|
13
13
|
iqm/pulla/interface.py,sha256=QquVKhOl2fs2V03fqQJq5sIEaIGiYvetPKKNz_fWH54,3570
|
|
14
|
-
iqm/pulla/pulla.py,sha256=
|
|
14
|
+
iqm/pulla/pulla.py,sha256=kgcyoMe9a9VvD9Y7HLvFdaQaax8vJkP_OVRd7sftvjo,16166
|
|
15
15
|
iqm/pulla/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
16
|
iqm/pulla/quantum_architecture.py,sha256=mJH9e9fdkblg6LrgN7qd-Ui3Igawf-hGd2Z7ZclQg04,6260
|
|
17
17
|
iqm/pulla/utils.py,sha256=xVu4jLlSHX-_YQT1kB-zBiGy4wNy0YyOKZg4AGMB5DE,24748
|
|
@@ -19,9 +19,9 @@ iqm/pulla/utils_cirq.py,sha256=VtdO356D2RAh2lSVdaPm3ClJ9-nvC4jzhR9hP5QSQhI,793
|
|
|
19
19
|
iqm/pulla/utils_dd.py,sha256=SxYAuRBgvYELKjeXpFbP4mM0xCCivDk7WUHw7oEXfMo,1695
|
|
20
20
|
iqm/pulla/utils_qir.py,sha256=uNEiqBczv7rX8tAqcg7TX-si0P-ZdDcPTMOVfi5eb28,11567
|
|
21
21
|
iqm/pulla/utils_qiskit.py,sha256=pbb2fEJAdxqd6hW9_Qgvpvy0P2H81zTJ1QLahe4Tx6U,9482
|
|
22
|
-
iqm_pulla-11.
|
|
23
|
-
iqm_pulla-11.
|
|
24
|
-
iqm_pulla-11.
|
|
25
|
-
iqm_pulla-11.
|
|
26
|
-
iqm_pulla-11.
|
|
27
|
-
iqm_pulla-11.
|
|
22
|
+
iqm_pulla-11.3.0.dist-info/AUTHORS.rst,sha256=iCStz7WP5Jk7uMnn9jRA4ybS14X4yeUW2SsWE-OTaRk,328
|
|
23
|
+
iqm_pulla-11.3.0.dist-info/LICENSE.txt,sha256=cCj_biRA4Q8A77vxR8AuvAf-DZ5G79yxR_3lYY6TrmA,11333
|
|
24
|
+
iqm_pulla-11.3.0.dist-info/METADATA,sha256=Tupb5P7iJM8flI6Cvj8DrZkGYyCq4mDH395PT5lFwNs,17700
|
|
25
|
+
iqm_pulla-11.3.0.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
|
|
26
|
+
iqm_pulla-11.3.0.dist-info/top_level.txt,sha256=NB4XRfyDS6_wG9gMsyX-9LTU7kWnTQxNvkbzIxGv3-c,4
|
|
27
|
+
iqm_pulla-11.3.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|