iqm-pulse 12.5.0__tar.gz → 12.7.0__tar.gz
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_pulse-12.5.0 → iqm_pulse-12.7.0}/CHANGELOG.rst +32 -8
- iqm_pulse-12.7.0/MANIFEST.in +4 -0
- {iqm_pulse-12.5.0/src/iqm_pulse.egg-info → iqm_pulse-12.7.0}/PKG-INFO +3 -4
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/README.rst +1 -1
- iqm_pulse-12.7.0/docs/changelog.rst +8 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/pyproject.toml +4 -5
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/requirements/base.txt +2 -2
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm/pulse/builder.py +22 -20
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm/pulse/gate_implementation.py +1 -1
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm/pulse/gates/__init__.py +7 -1
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm/pulse/gates/conditional.py +32 -13
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm/pulse/gates/default_gates.py +6 -1
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm/pulse/gates/measure.py +135 -17
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm/pulse/playlist/instructions.py +121 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm/pulse/playlist/waveforms.py +3 -6
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm/pulse/timebox.py +63 -2
- iqm_pulse-12.7.0/src/iqm/pulse/utils.py +195 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0/src/iqm_pulse.egg-info}/PKG-INFO +3 -4
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm_pulse.egg-info/SOURCES.txt +1 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm_pulse.egg-info/requires.txt +0 -1
- iqm_pulse-12.7.0/tests/__init__.py +0 -0
- iqm_pulse-12.7.0/version.txt +1 -0
- iqm_pulse-12.5.0/MANIFEST.in +0 -10
- iqm_pulse-12.5.0/docs/changelog.rst +0 -2
- iqm_pulse-12.5.0/src/iqm/pulse/utils.py +0 -109
- iqm_pulse-12.5.0/version.txt +0 -1
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/LICENSE.txt +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/docs/API.rst +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/docs/Makefile +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/docs/_static/.gitignore +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/docs/_static/css/custom.css +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/docs/_static/images/favicon.ico +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/docs/_static/images/feedback_timing.svg +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/docs/_static/images/logo.png +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/docs/_static/images/playlist_breakdown.svg +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/docs/_static/images/pulse_timing.svg +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/docs/_static/images/readout_timing.svg +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/docs/_templates/autosummary-class-template.rst +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/docs/_templates/autosummary-module-template.rst +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/docs/concepts.rst +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/docs/conf.py +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/docs/custom_gates.rst +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/docs/index.rst +1 -1
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/docs/license.rst +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/docs/pulse_timing.rst +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/docs/references.bib +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/docs/references.rst +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/docs/using_builder.rst +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/requirements/base.in +0 -0
- /iqm_pulse-12.5.0/src/iqm/pulse/py.typed → /iqm_pulse-12.7.0/requirements/base.in.internal +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/setup.cfg +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/setup.py +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm/pulse/__init__.py +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm/pulse/base_utils.py +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm/pulse/circuit_operations.py +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm/pulse/gates/barrier.py +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm/pulse/gates/cz.py +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm/pulse/gates/delay.py +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm/pulse/gates/enums.py +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm/pulse/gates/flux_multiplexer.py +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm/pulse/gates/move.py +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm/pulse/gates/prx.py +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm/pulse/gates/reset.py +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm/pulse/gates/rz.py +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm/pulse/gates/sx.py +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm/pulse/gates/u.py +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm/pulse/playlist/__init__.py +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm/pulse/playlist/channel.py +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm/pulse/playlist/fast_drag.py +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm/pulse/playlist/hd_drag.py +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm/pulse/playlist/playlist.py +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm/pulse/playlist/schedule.py +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm/pulse/playlist/visualisation/__init__.py +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm/pulse/playlist/visualisation/base.py +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm/pulse/playlist/visualisation/templates/playlist_inspection.jinja2 +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm/pulse/playlist/visualisation/templates/static/logo.png +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm/pulse/playlist/visualisation/templates/static/moment.min.js +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm/pulse/playlist/visualisation/templates/static/vis-timeline-graph2d.min.css +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm/pulse/playlist/visualisation/templates/static/vis-timeline-graph2d.min.js +0 -0
- /iqm_pulse-12.5.0/tests/__init__.py → /iqm_pulse-12.7.0/src/iqm/pulse/py.typed +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm/pulse/quantum_ops.py +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm/pulse/scheduler.py +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm/pulse/validation.py +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm_pulse.egg-info/dependency_links.txt +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/src/iqm_pulse.egg-info/top_level.txt +0 -0
- {iqm_pulse-12.5.0 → iqm_pulse-12.7.0}/tests/.pylintrc +0 -0
|
@@ -1,6 +1,30 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
Version 12.7.0 (2025-11-19)
|
|
2
|
+
===========================
|
|
3
|
+
|
|
4
|
+
Features
|
|
5
|
+
--------
|
|
6
|
+
|
|
7
|
+
- Playlist generation now does acq discovery
|
|
8
|
+
- Add ``Fast_Measure_CustomWaveForms`` and ``Fast_Measure_Constant`` measure implementations that block the locus qubit
|
|
9
|
+
drive and flux channels only for the duration of the physical probe pulse (plus additional calibratable dead time to
|
|
10
|
+
account for e.g. ring-down delay).
|
|
11
|
+
- The implementation ``Fast_Measure_CustomWaveForms`` is simplified such that it no longer requires additional virtual
|
|
12
|
+
probe channels.
|
|
13
|
+
|
|
14
|
+
Bug fixes
|
|
15
|
+
---------
|
|
16
|
+
|
|
17
|
+
- Fix `Fast_Measure_CustomWaveForms` not being scheduled correctly in some cases involving deep TimeBox structures.
|
|
18
|
+
- Fix `Fast_Measure_CustomWaveForms.time_trace` which was broken.
|
|
19
|
+
|
|
20
|
+
Version 12.6.0 (2025-10-23)
|
|
21
|
+
===========================
|
|
22
|
+
|
|
23
|
+
Features
|
|
24
|
+
--------
|
|
25
|
+
|
|
26
|
+
- ``cc_prx`` gate now supports ``prx`` gate implementations that consists of multiple drive IQ pulses,
|
|
27
|
+
e.g. ones that use the ``sx`` gate. As a result, the ``reset`` operation now also works with them.
|
|
4
28
|
|
|
5
29
|
Version 12.5.0 (2025-10-09)
|
|
6
30
|
===========================
|
|
@@ -336,7 +360,7 @@ Version 8.13.0 (2025-04-07)
|
|
|
336
360
|
Features
|
|
337
361
|
--------
|
|
338
362
|
|
|
339
|
-
- Fix package version in published docs footers, :issue:`SW-1392`.
|
|
363
|
+
- Fix package version in published docs footers, :issue:`SW-1392`.
|
|
340
364
|
|
|
341
365
|
Version 8.12.0 (2025-04-03)
|
|
342
366
|
===========================
|
|
@@ -369,7 +393,7 @@ Version 8.9.0 (2025-03-28)
|
|
|
369
393
|
Features
|
|
370
394
|
--------
|
|
371
395
|
|
|
372
|
-
- Reworked the way default gates (operations) are defined so they are decoupled from their implementations. This separation allows for the deletion of default implementations without losing information about its designated name.
|
|
396
|
+
- Reworked the way default gates (operations) are defined so they are decoupled from their implementations. This separation allows for the deletion of default implementations without losing information about its designated name.
|
|
373
397
|
- The majority of the original functionality stays the same.
|
|
374
398
|
- The ``register_implementation`` function has been split into several different functions to improve readability and testing, as seen below::
|
|
375
399
|
|
|
@@ -381,8 +405,8 @@ Features
|
|
|
381
405
|
v
|
|
382
406
|
``validate_implementation`` --> ``set_default``
|
|
383
407
|
|
|
384
|
-
- The ``build_quantum_ops`` function in builder.py has been split into several functions as well.
|
|
385
|
-
- Trying to modify the implementation class of an existing or default gate implementation yields an error.
|
|
408
|
+
- The ``build_quantum_ops`` function in builder.py has been split into several functions as well.
|
|
409
|
+
- Trying to modify the implementation class of an existing or default gate implementation yields an error.
|
|
386
410
|
|
|
387
411
|
|
|
388
412
|
|
|
@@ -1187,7 +1211,7 @@ Version 1.5 (2024-07-05)
|
|
|
1187
1211
|
|
|
1188
1212
|
Features
|
|
1189
1213
|
--------
|
|
1190
|
-
- Bump exa-common to 25.3
|
|
1214
|
+
- Bump exa-common to 25.3
|
|
1191
1215
|
|
|
1192
1216
|
|
|
1193
1217
|
Version 1.4 (2024-07-04)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: iqm-pulse
|
|
3
|
-
Version: 12.
|
|
3
|
+
Version: 12.7.0
|
|
4
4
|
Summary: A Python-based project for providing interface and implementations for control pulses.
|
|
5
5
|
Author-email: IQM Finland Oy <info@meetiqm.com>
|
|
6
6
|
License: Apache License
|
|
@@ -204,7 +204,7 @@ License: Apache License
|
|
|
204
204
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
205
205
|
See the License for the specific language governing permissions and
|
|
206
206
|
limitations under the License.
|
|
207
|
-
Project-URL: Documentation, https://
|
|
207
|
+
Project-URL: Documentation, https://docs.meetiqm.com/iqm-pulse/
|
|
208
208
|
Project-URL: Homepage, https://pypi.org/project/iqm-pulse/
|
|
209
209
|
Classifier: Development Status :: 4 - Beta
|
|
210
210
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
@@ -213,7 +213,6 @@ Classifier: Intended Audience :: Science/Research
|
|
|
213
213
|
Requires-Python: >=3.11
|
|
214
214
|
Description-Content-Type: text/x-rst
|
|
215
215
|
License-File: LICENSE.txt
|
|
216
|
-
Requires-Dist: iqm-exa-common<28,>=27
|
|
217
216
|
Requires-Dist: iqm-data-definitions<3.0,>=2.18
|
|
218
217
|
Requires-Dist: python-rapidjson==1.20
|
|
219
218
|
Requires-Dist: jinja2==3.0.3
|
|
@@ -226,7 +225,7 @@ IQM Pulse library
|
|
|
226
225
|
|
|
227
226
|
A Python-based project for providing interface and implementations for control pulses.
|
|
228
227
|
|
|
229
|
-
See `API documentation <https://
|
|
228
|
+
See `API documentation <https://docs.meetiqm.com/iqm-pulse/>`_.
|
|
230
229
|
|
|
231
230
|
Copyright
|
|
232
231
|
---------
|
|
@@ -3,7 +3,7 @@ IQM Pulse library
|
|
|
3
3
|
|
|
4
4
|
A Python-based project for providing interface and implementations for control pulses.
|
|
5
5
|
|
|
6
|
-
See `API documentation <https://
|
|
6
|
+
See `API documentation <https://docs.meetiqm.com/iqm-pulse/>`_.
|
|
7
7
|
|
|
8
8
|
Copyright
|
|
9
9
|
---------
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
# This file is managed by monotool.py, do not edit by hand
|
|
2
1
|
[build-system]
|
|
3
2
|
build-backend = "setuptools.build_meta"
|
|
4
3
|
requires = [ "setuptools", "setuptools_scm[toml]",]
|
|
@@ -18,7 +17,7 @@ email = "info@meetiqm.com"
|
|
|
18
17
|
file = "LICENSE.txt"
|
|
19
18
|
|
|
20
19
|
[project.urls]
|
|
21
|
-
Documentation = "https://
|
|
20
|
+
Documentation = "https://docs.meetiqm.com/iqm-pulse/"
|
|
22
21
|
Homepage = "https://pypi.org/project/iqm-pulse/"
|
|
23
22
|
|
|
24
23
|
[tool.mypy]
|
|
@@ -57,7 +56,7 @@ nb_diff_ignore = [ "/metadata/language_info", "/metadata/widgets", "/cells/*/exe
|
|
|
57
56
|
|
|
58
57
|
[tool.ruff.lint]
|
|
59
58
|
ignore = [ "D203", "D213",]
|
|
60
|
-
select = [ "E4", "E7", "E9", "E5", "F", "Q", "PL", "I", "D", "UP007", "UP006", "UP035", "ANN001", "ANN201", "ANN202",]
|
|
59
|
+
select = [ "E4", "E7", "E9", "E5", "F", "Q", "PL", "I", "D", "UP007", "UP006", "UP035", "ANN001", "ANN201", "ANN202", "NPY201",]
|
|
61
60
|
unfixable = [ "F401",]
|
|
62
61
|
|
|
63
62
|
[tool.ruff.lint.isort]
|
|
@@ -68,10 +67,10 @@ known-third-party = [ "exa", "iqm",]
|
|
|
68
67
|
relative-imports-order = "closest-to-furthest"
|
|
69
68
|
|
|
70
69
|
[tool.ruff.lint.per-file-ignores]
|
|
71
|
-
"**/__init__.py" = [ "F401", "PLR0402",]
|
|
70
|
+
"**/__init__.py" = [ "D104", "F401", "PLR0402",]
|
|
72
71
|
"**/docs/*" = [ "E402", "D100",]
|
|
73
72
|
"**/setup.py" = [ "D100", "D103", "I001", "ANN201",]
|
|
74
|
-
"**/src/*" = [ "PLR2004", "D400", "D415", "D205", "D401", "D417", "D100", "
|
|
73
|
+
"**/src/*" = [ "PLR2004", "D400", "D415", "D205", "D401", "D417", "D100", "D107", "D105", "D102", "D404",]
|
|
75
74
|
"**/tests/*" = [ "F632", "PLR2004", "PLR0402", "PLC0414", "D", "ANN001", "ANN201", "ANN202",]
|
|
76
75
|
|
|
77
76
|
[tool.ruff.lint.pylint]
|
|
@@ -15,8 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
from __future__ import annotations
|
|
17
17
|
|
|
18
|
-
from collections import
|
|
19
|
-
from collections.abc import Iterable
|
|
18
|
+
from collections.abc import Iterable, Sequence
|
|
20
19
|
import copy
|
|
21
20
|
from dataclasses import dataclass, field, replace
|
|
22
21
|
import itertools
|
|
@@ -56,6 +55,7 @@ from iqm.pulse.playlist.instructions import (
|
|
|
56
55
|
Instruction,
|
|
57
56
|
IQPulse,
|
|
58
57
|
MultiplexedIQPulse,
|
|
58
|
+
ReadoutMetrics,
|
|
59
59
|
ReadoutTrigger,
|
|
60
60
|
RealPulse,
|
|
61
61
|
ThresholdStateDiscrimination,
|
|
@@ -492,6 +492,10 @@ class ScheduleBuilder:
|
|
|
492
492
|
"""Probe line channel for the probe line ``component`` belongs to.
|
|
493
493
|
|
|
494
494
|
See :meth:`.get_drive_channel`.
|
|
495
|
+
|
|
496
|
+
Args:
|
|
497
|
+
component: name of a QPU component (typically qubit) to probe
|
|
498
|
+
|
|
495
499
|
"""
|
|
496
500
|
probe_line = self.chip_topology.component_to_probe_line.get(component, None)
|
|
497
501
|
if probe_line is None:
|
|
@@ -1038,7 +1042,7 @@ class ScheduleBuilder:
|
|
|
1038
1042
|
|
|
1039
1043
|
def timeboxes_to_front_padded_playlist(
|
|
1040
1044
|
self, boxes: Iterable[TimeBox], *, neighborhood: int = 0
|
|
1041
|
-
) -> tuple[Playlist,
|
|
1045
|
+
) -> tuple[Playlist, ReadoutMetrics]:
|
|
1042
1046
|
"""Temporary helper function, for converting a sequence of TimeBoxes to a Playlist.
|
|
1043
1047
|
|
|
1044
1048
|
Each individual TimeBox in ``boxes`` is resolved into a Schedule, and then
|
|
@@ -1057,8 +1061,7 @@ class ScheduleBuilder:
|
|
|
1057
1061
|
blocks only the defined locus components and any other components which have occupied channels.
|
|
1058
1062
|
|
|
1059
1063
|
Returns:
|
|
1060
|
-
playlist that implements ``boxes`` and the
|
|
1061
|
-
implementations (of the format ``<QuantumOp name>.<impl name>``).
|
|
1064
|
+
playlist that implements ``boxes`` and the readout metrics for that playlist.
|
|
1062
1065
|
|
|
1063
1066
|
"""
|
|
1064
1067
|
schedules = [self.resolve_timebox(box, neighborhood=neighborhood).cleanup() for box in boxes]
|
|
@@ -1102,7 +1105,7 @@ class ScheduleBuilder:
|
|
|
1102
1105
|
playlist that implements ``boxes``
|
|
1103
1106
|
|
|
1104
1107
|
"""
|
|
1105
|
-
return self.build_playlist(self.timebox_to_schedule(box, neighborhood=neighborhood) for box in boxes)[0]
|
|
1108
|
+
return self.build_playlist([self.timebox_to_schedule(box, neighborhood=neighborhood) for box in boxes])[0]
|
|
1106
1109
|
|
|
1107
1110
|
def timebox_to_schedule(
|
|
1108
1111
|
self,
|
|
@@ -1453,8 +1456,8 @@ class ScheduleBuilder:
|
|
|
1453
1456
|
schedule.append(ch, Block(T))
|
|
1454
1457
|
|
|
1455
1458
|
def build_playlist( # noqa: PLR0915
|
|
1456
|
-
self, schedules:
|
|
1457
|
-
) -> tuple[Playlist,
|
|
1459
|
+
self, schedules: Sequence[Schedule], finish_schedules: bool = True
|
|
1460
|
+
) -> tuple[Playlist, ReadoutMetrics]:
|
|
1458
1461
|
"""Build a playlist from a number of instruction schedules.
|
|
1459
1462
|
|
|
1460
1463
|
This involves compressing the schedules so that no duplicate information
|
|
@@ -1468,8 +1471,7 @@ class ScheduleBuilder:
|
|
|
1468
1471
|
unless some process has already finalised them before calling this function.
|
|
1469
1472
|
|
|
1470
1473
|
Returns:
|
|
1471
|
-
playlist containing the schedules and the
|
|
1472
|
-
implementations (of the format ``<QuantumOp name>.<impl name>``).
|
|
1474
|
+
playlist containing the schedules and the readout metrics for this playlist.
|
|
1473
1475
|
|
|
1474
1476
|
Raises:
|
|
1475
1477
|
ValueError: if the schedules contain channels with non-uniform sampling rates
|
|
@@ -1492,6 +1494,7 @@ class ScheduleBuilder:
|
|
|
1492
1494
|
|
|
1493
1495
|
pl = Playlist()
|
|
1494
1496
|
mapped_instructions: dict[str, dict[int | Instruction, Any]] = {}
|
|
1497
|
+
readout_metrics = ReadoutMetrics(num_segments=len(schedules))
|
|
1495
1498
|
|
|
1496
1499
|
def _append_to_schedule(sc_schedule: SC_Schedule, channel_name: str, instr: Instruction) -> None:
|
|
1497
1500
|
"""Append ``instr`` to ``sc_schedule`` into the channel``channel_name``."""
|
|
@@ -1517,15 +1520,15 @@ class ScheduleBuilder:
|
|
|
1517
1520
|
|
|
1518
1521
|
# add the schedules in the playlist
|
|
1519
1522
|
|
|
1520
|
-
label_to_implementation: dict[str, set[str]] = defaultdict(set)
|
|
1521
|
-
|
|
1522
1523
|
def _map_instruction(inst: Instruction) -> sc_instructions.Instruction:
|
|
1523
1524
|
"""TODO only necessary until SC has been updated to use the iqm.pulse Instruction class."""
|
|
1524
1525
|
operation: Any
|
|
1525
1526
|
|
|
1526
1527
|
def _map_acquisition(acq: AcquisitionMethod) -> sc_instructions.AcquisitionMethod:
|
|
1527
|
-
if acq
|
|
1528
|
-
|
|
1528
|
+
if isinstance(acq, TimeTrace):
|
|
1529
|
+
return sc_instructions.TimeTrace(
|
|
1530
|
+
label=acq.label, delay_samples=acq.delay_samples, duration_samples=acq.duration_samples
|
|
1531
|
+
)
|
|
1529
1532
|
if isinstance(acq, ThresholdStateDiscrimination):
|
|
1530
1533
|
return sc_instructions.ThresholdStateDiscrimination(
|
|
1531
1534
|
label=acq.label,
|
|
@@ -1540,10 +1543,7 @@ class ScheduleBuilder:
|
|
|
1540
1543
|
delay_samples=acq.delay_samples,
|
|
1541
1544
|
weights=_map_instruction(acq.weights).operation,
|
|
1542
1545
|
)
|
|
1543
|
-
|
|
1544
|
-
return sc_instructions.TimeTrace(
|
|
1545
|
-
label=acq.label, delay_samples=acq.delay_samples, duration_samples=acq.duration_samples
|
|
1546
|
-
)
|
|
1546
|
+
|
|
1547
1547
|
raise ValueError(f"Unknown AcquisitionMethod {acq}")
|
|
1548
1548
|
|
|
1549
1549
|
if isinstance(inst, Wait):
|
|
@@ -1587,7 +1587,7 @@ class ScheduleBuilder:
|
|
|
1587
1587
|
return sc_instructions.Instruction(duration_samples=int(inst.duration), operation=operation)
|
|
1588
1588
|
|
|
1589
1589
|
# NOTE that there is no implicit right-alignment or equal duration for schedules, unlike in old-style playlists!
|
|
1590
|
-
for schedule in schedules:
|
|
1590
|
+
for seg_idx, schedule in enumerate(schedules):
|
|
1591
1591
|
finished_schedule = self._finish_schedule(schedule) if finish_schedules else schedule
|
|
1592
1592
|
sc_schedule = SC_Schedule()
|
|
1593
1593
|
for channel_name, segment in finished_schedule.items():
|
|
@@ -1596,6 +1596,8 @@ class ScheduleBuilder:
|
|
|
1596
1596
|
pl.add_channel(channel)
|
|
1597
1597
|
prev_wait = None
|
|
1598
1598
|
for instruction in segment:
|
|
1599
|
+
if isinstance(instruction, ReadoutTrigger):
|
|
1600
|
+
readout_metrics.extend(instruction, seg_idx)
|
|
1599
1601
|
# convert all NONSOLID instructions into Waits
|
|
1600
1602
|
if finish_schedules and (isinstance(instruction, NONSOLID) or isinstance(instruction, Wait)):
|
|
1601
1603
|
if instruction.duration > 0:
|
|
@@ -1614,7 +1616,7 @@ class ScheduleBuilder:
|
|
|
1614
1616
|
if prev_wait:
|
|
1615
1617
|
_append_to_schedule(sc_schedule, channel_name, prev_wait)
|
|
1616
1618
|
pl.segments.append(sc_schedule)
|
|
1617
|
-
return pl,
|
|
1619
|
+
return pl, readout_metrics
|
|
1618
1620
|
|
|
1619
1621
|
def _set_gate_implementation_shortcut(self, op_name: str) -> None:
|
|
1620
1622
|
"""Create shortcut for `self.get_implementation(<op_name>, ...)` as `self.<op_name>(...)`.
|
|
@@ -602,7 +602,7 @@ class SinglePulseGate(GateImplementation):
|
|
|
602
602
|
return self.builder.channels[self.channel].duration_to_seconds(self.pulse.duration)
|
|
603
603
|
|
|
604
604
|
|
|
605
|
-
def init_subclass_composite(gate_class: type[CompositeGate]) -> None:
|
|
605
|
+
def init_subclass_composite(gate_class: type[CompositeGate]) -> None: # noqa: D103
|
|
606
606
|
if not gate_class.registered_gates:
|
|
607
607
|
# this would be pointless
|
|
608
608
|
raise ValueError(f"CompositeGate {gate_class.__name__} has no registered gates.")
|
|
@@ -49,7 +49,12 @@ from iqm.pulse.gates.cz import (
|
|
|
49
49
|
from iqm.pulse.gates.default_gates import _implementation_library, _quantum_ops_library
|
|
50
50
|
from iqm.pulse.gates.delay import Delay
|
|
51
51
|
from iqm.pulse.gates.flux_multiplexer import FluxMultiplexer_SampleLinear
|
|
52
|
-
from iqm.pulse.gates.measure import
|
|
52
|
+
from iqm.pulse.gates.measure import (
|
|
53
|
+
Fast_Measure_Constant,
|
|
54
|
+
Measure_Constant,
|
|
55
|
+
Measure_Constant_Qnd,
|
|
56
|
+
Shelved_Measure_Constant,
|
|
57
|
+
)
|
|
53
58
|
from iqm.pulse.gates.move import MOVE_CRF_CRF, MOVE_SLEPIAN_CRF, MOVE_TGSS_CRF
|
|
54
59
|
from iqm.pulse.gates.prx import (
|
|
55
60
|
Constant_PRX_with_smooth_rise_fall,
|
|
@@ -105,6 +110,7 @@ _exposed_implementations: dict[str, type[GateImplementation]] = {
|
|
|
105
110
|
FluxPulseGate_CRF_CRF,
|
|
106
111
|
Measure_Constant,
|
|
107
112
|
Measure_Constant_Qnd,
|
|
113
|
+
Fast_Measure_Constant,
|
|
108
114
|
Shelved_Measure_Constant,
|
|
109
115
|
PRX_ModulatedDRAGCosineRiseFall,
|
|
110
116
|
MOVE_CRF_CRF,
|
|
@@ -18,10 +18,10 @@ import numpy as np
|
|
|
18
18
|
from exa.common.data.parameter import CollectionType, Parameter
|
|
19
19
|
from iqm.pulse.gate_implementation import CompositeGate
|
|
20
20
|
from iqm.pulse.gates.measure import FEEDBACK_KEY
|
|
21
|
-
from iqm.pulse.
|
|
22
|
-
from iqm.pulse.playlist.instructions import Block, ConditionalInstruction, Wait
|
|
21
|
+
from iqm.pulse.playlist.instructions import Block, ConditionalInstruction, IQPulse, Wait
|
|
23
22
|
from iqm.pulse.playlist.schedule import Schedule
|
|
24
23
|
from iqm.pulse.timebox import TimeBox
|
|
24
|
+
from iqm.pulse.utils import fuse_iq_pulses
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
class CCPRX_Composite(CompositeGate):
|
|
@@ -30,6 +30,12 @@ class CCPRX_Composite(CompositeGate):
|
|
|
30
30
|
Applies a PRX gate conditioned on a discriminated readout result obtained in the same segment (active feedback).
|
|
31
31
|
Applies a PRX gate if the result is 1, and a Wait of equal duration if the result is 0.
|
|
32
32
|
Uses the default implementation of PRX underneath, so no extra calibration is needed.
|
|
33
|
+
|
|
34
|
+
.. note::
|
|
35
|
+
|
|
36
|
+
Assumes that the PRX gate implementation used only consists of IQPulse instructions on the drive channel
|
|
37
|
+
of its locus qubit.
|
|
38
|
+
|
|
33
39
|
"""
|
|
34
40
|
|
|
35
41
|
registered_gates = ("prx",)
|
|
@@ -70,30 +76,43 @@ class CCPRX_Composite(CompositeGate):
|
|
|
70
76
|
|
|
71
77
|
"""
|
|
72
78
|
qubit = self.locus[0]
|
|
73
|
-
|
|
79
|
+
drive_channel = self.builder.get_drive_channel(qubit)
|
|
80
|
+
prx_gate = self.build("prx", self.locus)
|
|
81
|
+
|
|
82
|
+
# NOTE assumes that the PRX gate only has IQPulse instructions on drive_channel
|
|
83
|
+
timebox: TimeBox = prx_gate(angle, phase) # type: ignore[assignment]
|
|
84
|
+
if not timebox.atom:
|
|
85
|
+
raise RuntimeError("Received non-atomic PRX timebox.")
|
|
86
|
+
prx_instructions = timebox.atom[drive_channel]
|
|
87
|
+
iq_pulses = [inst for inst in prx_instructions if isinstance(inst, IQPulse)]
|
|
88
|
+
if len(iq_pulses) != len(prx_instructions):
|
|
89
|
+
raise RuntimeError(f"PRX drive channel has non-IQPulse instructions: {prx_instructions}")
|
|
90
|
+
|
|
91
|
+
if len(iq_pulses) > 1:
|
|
92
|
+
iq_pulse = fuse_iq_pulses(iq_pulses)
|
|
93
|
+
else:
|
|
94
|
+
iq_pulse = iq_pulses[0]
|
|
74
95
|
|
|
75
|
-
|
|
76
|
-
# FIXME assumes PRX gates only use this one implementation as the default,
|
|
77
|
-
# with just a drive channel and a single IQPulse.
|
|
78
|
-
pulse = prx_gate(angle, phase).atom[prx_gate.channel][0] # type: ignore[union-attr,index]
|
|
79
|
-
wait = Wait(pulse.duration) # idling, can be replaced with a DD sequence later on
|
|
96
|
+
wait = Wait(iq_pulse.duration) # idling, can be replaced with a DD sequence later on
|
|
80
97
|
|
|
81
98
|
# TODO: use the actual inputted label when the HW supports many labels per drive channel
|
|
82
99
|
default_label = f"{feedback_qubit}__{FEEDBACK_KEY}"
|
|
83
|
-
|
|
84
|
-
duration=
|
|
100
|
+
conditional_instruction = ConditionalInstruction(
|
|
101
|
+
duration=iq_pulse.duration,
|
|
102
|
+
condition=default_label,
|
|
103
|
+
outcomes=(wait, iq_pulse),
|
|
85
104
|
)
|
|
86
105
|
delays = self.calibration_data["control_delays"]
|
|
87
106
|
if len(delays) == 0:
|
|
88
107
|
raise ValueError(f"'control_delays' for '{self.name}' on {qubit} is empty (not calibrated).")
|
|
89
108
|
|
|
90
|
-
possible_sources = [c for c in self.builder.get_virtual_feedback_channels(qubit) if
|
|
109
|
+
possible_sources = [c for c in self.builder.get_virtual_feedback_channels(qubit) if drive_channel in c]
|
|
91
110
|
if len(delays) != len(possible_sources):
|
|
92
111
|
raise ValueError(
|
|
93
112
|
f"Not the correct amount of calibration values for 'control_delays'. Need {len(possible_sources)}"
|
|
94
113
|
f"values, got {delays}."
|
|
95
114
|
)
|
|
96
|
-
virtual_channel_name = self.builder.get_virtual_feedback_channel_for(
|
|
115
|
+
virtual_channel_name = self.builder.get_virtual_feedback_channel_for(drive_channel, feedback_qubit)
|
|
97
116
|
delay = delays[possible_sources.index(virtual_channel_name)]
|
|
98
117
|
virtual_channel = self.builder.channels[virtual_channel_name]
|
|
99
118
|
delay_samples = virtual_channel.duration_to_int_samples(
|
|
@@ -106,7 +125,7 @@ class CCPRX_Composite(CompositeGate):
|
|
|
106
125
|
)
|
|
107
126
|
delay_box.neighborhood_components = {0: {virtual_channel_name}}
|
|
108
127
|
cond = TimeBox.atomic(
|
|
109
|
-
Schedule({virtual_channel_name: [Block(0)],
|
|
128
|
+
Schedule({virtual_channel_name: [Block(0)], drive_channel: [conditional_instruction]}),
|
|
110
129
|
locus_components=[qubit],
|
|
111
130
|
label=f"Conditional PRX for {qubit}",
|
|
112
131
|
)
|
|
@@ -38,7 +38,11 @@ from iqm.pulse.gates.cz import (
|
|
|
38
38
|
)
|
|
39
39
|
from iqm.pulse.gates.delay import Delay
|
|
40
40
|
from iqm.pulse.gates.flux_multiplexer import FluxMultiplexer_SampleLinear
|
|
41
|
-
from iqm.pulse.gates.measure import
|
|
41
|
+
from iqm.pulse.gates.measure import (
|
|
42
|
+
Fast_Measure_Constant,
|
|
43
|
+
Measure_Constant,
|
|
44
|
+
Shelved_Measure_Constant,
|
|
45
|
+
)
|
|
42
46
|
from iqm.pulse.gates.move import MOVE_CRF_CRF, MOVE_SLEPIAN_CRF, MOVE_TGSS_CRF
|
|
43
47
|
from iqm.pulse.gates.prx import (
|
|
44
48
|
PRX_DRAGCosineRiseFall,
|
|
@@ -68,6 +72,7 @@ _implementation_library: dict[str, dict[str, type[GateImplementation]]] = {
|
|
|
68
72
|
"delay": {"wait": Delay},
|
|
69
73
|
"measure": {
|
|
70
74
|
"constant": Measure_Constant,
|
|
75
|
+
"fast_constant": Fast_Measure_Constant,
|
|
71
76
|
},
|
|
72
77
|
"measure_fidelity": {
|
|
73
78
|
"constant": Measure_Constant,
|