iqm-pulse 9.16.0__py3-none-any.whl → 9.18.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/pulse/builder.py +58 -72
- iqm/pulse/gates/__init__.py +2 -1
- iqm/pulse/gates/default_gates.py +2 -2
- iqm/pulse/gates/move.py +8 -1
- {iqm_pulse-9.16.0.dist-info → iqm_pulse-9.18.0.dist-info}/METADATA +1 -1
- {iqm_pulse-9.16.0.dist-info → iqm_pulse-9.18.0.dist-info}/RECORD +9 -9
- {iqm_pulse-9.16.0.dist-info → iqm_pulse-9.18.0.dist-info}/LICENSE.txt +0 -0
- {iqm_pulse-9.16.0.dist-info → iqm_pulse-9.18.0.dist-info}/WHEEL +0 -0
- {iqm_pulse-9.16.0.dist-info → iqm_pulse-9.18.0.dist-info}/top_level.txt +0 -0
iqm/pulse/builder.py
CHANGED
|
@@ -18,7 +18,6 @@ from __future__ import annotations
|
|
|
18
18
|
from collections.abc import Iterable
|
|
19
19
|
import copy
|
|
20
20
|
from dataclasses import dataclass, field, replace
|
|
21
|
-
import functools
|
|
22
21
|
import itertools
|
|
23
22
|
import logging
|
|
24
23
|
from types import MethodType
|
|
@@ -63,7 +62,7 @@ from iqm.pulse.playlist.instructions import (
|
|
|
63
62
|
Wait,
|
|
64
63
|
)
|
|
65
64
|
from iqm.pulse.playlist.playlist import Playlist
|
|
66
|
-
from iqm.pulse.playlist.schedule import
|
|
65
|
+
from iqm.pulse.playlist.schedule import Schedule, Segment
|
|
67
66
|
from iqm.pulse.quantum_ops import QuantumOp, QuantumOpTable, validate_locus_calibration, validate_op_calibration
|
|
68
67
|
from iqm.pulse.scheduler import (
|
|
69
68
|
NONSOLID,
|
|
@@ -956,14 +955,8 @@ class ScheduleBuilder:
|
|
|
956
955
|
def _finish_schedule(self, schedule: Schedule) -> Schedule:
|
|
957
956
|
"""Finishes the instruction schedule.
|
|
958
957
|
|
|
959
|
-
* filters out zero-duration Blocks and Waits
|
|
960
|
-
* converts all spacer instructions used during scheduling to Waits
|
|
961
|
-
* merges consequent Waits
|
|
962
958
|
* removes channels that only have Waits in them
|
|
963
|
-
|
|
964
|
-
This should be the final step of the schedule building process, after this the
|
|
965
|
-
resulting Schedule can no longer be consistently extended with another (since
|
|
966
|
-
all the spacer instructions are gone).
|
|
959
|
+
* fuses long-distance Rz corrections to the correct drive pulses
|
|
967
960
|
|
|
968
961
|
Args:
|
|
969
962
|
schedule: schedule to finish
|
|
@@ -973,46 +966,15 @@ class ScheduleBuilder:
|
|
|
973
966
|
|
|
974
967
|
"""
|
|
975
968
|
has_long_distance_rzs = False
|
|
976
|
-
|
|
977
|
-
def segment_pass(inst: Instruction) -> Instruction:
|
|
978
|
-
"""Convert Blocks and Nothings to Waits. Also checks for FluxPulses that have long-distance VirtualZ
|
|
979
|
-
corrections in order to determine if these need handling (for performance reasons, we want to do this
|
|
980
|
-
step only on-demand).
|
|
981
|
-
"""
|
|
982
|
-
nonlocal has_long_distance_rzs
|
|
983
|
-
if isinstance(inst, NONSOLID) and not isinstance(inst, Wait):
|
|
984
|
-
return Wait(inst.duration)
|
|
985
|
-
if isinstance(inst, FluxPulse) and inst.rzs:
|
|
986
|
-
has_long_distance_rzs = True
|
|
987
|
-
return inst
|
|
988
|
-
|
|
989
|
-
def not_zero_block(inst: Instruction) -> bool:
|
|
990
|
-
"""Zero-duration Block instructions have a legitimate use (in barrier ops),
|
|
991
|
-
zero-duration Wait instructions are allowed for convenience.
|
|
992
|
-
Here we filter them out.
|
|
993
|
-
"""
|
|
994
|
-
return not (inst.duration < TOLERANCE and isinstance(inst, (Block, Wait)))
|
|
995
|
-
|
|
996
|
-
def merge_waits(result: list[Instruction], new: Instruction) -> list[Instruction]:
|
|
997
|
-
"""Merge consequent Wait instructions."""
|
|
998
|
-
if not result:
|
|
999
|
-
return [new] # first iteration
|
|
1000
|
-
last = result[-1]
|
|
1001
|
-
if isinstance(last, Wait) and isinstance(new, Wait):
|
|
1002
|
-
result[-1] = Wait(int(last.duration + new.duration)) # replace last with the combined wait
|
|
1003
|
-
else:
|
|
1004
|
-
result.append(new)
|
|
1005
|
-
return result
|
|
1006
|
-
|
|
1007
969
|
for channel in schedule.channels():
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
return
|
|
970
|
+
if "flux" in channel:
|
|
971
|
+
for inst in schedule[channel]:
|
|
972
|
+
if isinstance(inst, FluxPulse) and inst.rzs:
|
|
973
|
+
has_long_distance_rzs = True
|
|
974
|
+
break
|
|
975
|
+
if has_long_distance_rzs:
|
|
976
|
+
return self._fuse_long_distance_virtual_rzs(schedule)
|
|
977
|
+
return schedule.cleanup()
|
|
1016
978
|
|
|
1017
979
|
def _fuse_long_distance_virtual_rzs(self, schedule: Schedule) -> Schedule:
|
|
1018
980
|
"""Fuse long-distance (i.e. out-of-gate-locus) VirtualRZ corrections with the next drive pulse
|
|
@@ -1036,7 +998,11 @@ class ScheduleBuilder:
|
|
|
1036
998
|
for drive_channel, rz_angle in rzs.items():
|
|
1037
999
|
drive_sample_counter = 0
|
|
1038
1000
|
for drive_inst_idx, drive_inst in enumerate(schedule[drive_channel]):
|
|
1039
|
-
if
|
|
1001
|
+
if (
|
|
1002
|
+
not isinstance(drive_inst, Wait)
|
|
1003
|
+
and not isinstance(drive_inst, NONSOLID)
|
|
1004
|
+
and drive_sample_counter >= sample_counter
|
|
1005
|
+
):
|
|
1040
1006
|
fuse(
|
|
1041
1007
|
schedule_copy[drive_channel][drive_inst_idx],
|
|
1042
1008
|
drive_inst_idx,
|
|
@@ -1345,38 +1311,58 @@ class ScheduleBuilder:
|
|
|
1345
1311
|
}
|
|
1346
1312
|
|
|
1347
1313
|
pl = Playlist()
|
|
1348
|
-
mapped_instructions: dict[int
|
|
1349
|
-
|
|
1314
|
+
mapped_instructions: dict[str, dict[int, Any]] = {}
|
|
1315
|
+
|
|
1316
|
+
def _append_to_schedule(sc_schedule: SC_Schedule, channel_name: str, instr: Instruction) -> None:
|
|
1317
|
+
"""Append ``instr`` to ``sc_schedule`` into the channel``channel_name``."""
|
|
1318
|
+
try:
|
|
1319
|
+
# Check if instr can be used as a dictionary key, and use it if possible.
|
|
1320
|
+
# 2 dataclasses can have the same hash if their fields are identical. We must
|
|
1321
|
+
# distinguish between different Waveform classes which may have identical fields,
|
|
1322
|
+
# so we use the instruction itself as a key, so that the class is checked too.
|
|
1323
|
+
instr_id = hash(instr)
|
|
1324
|
+
except TypeError:
|
|
1325
|
+
instr_id = instr.id
|
|
1326
|
+
if instr_id not in mapped_instructions.setdefault(channel_name, {}):
|
|
1327
|
+
mapped = _map_instruction(instr)
|
|
1328
|
+
idx = pl.channel_descriptions[channel_name].add_instruction(mapped)
|
|
1329
|
+
sc_schedule.instructions.setdefault(channel_name, []).append(idx)
|
|
1330
|
+
mapped_instructions[channel_name][instr_id] = idx
|
|
1331
|
+
else:
|
|
1332
|
+
sc_schedule.instructions.setdefault(channel_name, []).append(
|
|
1333
|
+
mapped_instructions[channel_name][instr_id]
|
|
1334
|
+
)
|
|
1335
|
+
|
|
1336
|
+
# add the schedules in the playlist
|
|
1337
|
+
|
|
1350
1338
|
# NOTE that there is no implicit right-alignment or equal duration for schedules, unlike in old-style playlists!
|
|
1351
1339
|
for schedule in schedules:
|
|
1352
|
-
if finish_schedules
|
|
1353
|
-
schedule = self._finish_schedule(schedule) # noqa: PLW2901
|
|
1340
|
+
finished_schedule = self._finish_schedule(schedule) if finish_schedules else schedule
|
|
1354
1341
|
sc_schedule = SC_Schedule()
|
|
1355
|
-
for channel_name, segment in
|
|
1342
|
+
for channel_name, segment in finished_schedule.items():
|
|
1356
1343
|
if (channel := channel_descriptions.get(channel_name)) is None:
|
|
1357
|
-
# ignore virtual channels in the schedule
|
|
1358
1344
|
continue
|
|
1359
1345
|
pl.add_channel(channel)
|
|
1346
|
+
prev_wait = None
|
|
1360
1347
|
for instruction in segment:
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
except TypeError:
|
|
1369
|
-
instr_id = instruction.id
|
|
1370
|
-
is_mapped = instr_id in mapped_instructions
|
|
1371
|
-
if is_mapped:
|
|
1372
|
-
sc_schedule.add_to_segment(channel, mapped_instructions[instr_id])
|
|
1348
|
+
# convert all NONSOLID instructions into Waits
|
|
1349
|
+
if finish_schedules and (isinstance(instruction, NONSOLID) or isinstance(instruction, Wait)):
|
|
1350
|
+
if instruction.duration > 0:
|
|
1351
|
+
if prev_wait: # if the previous instruction was a Wait, combine durations
|
|
1352
|
+
prev_wait = Wait(prev_wait.duration + instruction.duration)
|
|
1353
|
+
else:
|
|
1354
|
+
prev_wait = Wait(instruction.duration)
|
|
1373
1355
|
else:
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1356
|
+
if prev_wait: # if there's a prev_wait not yet added to schedule, place it before instruction
|
|
1357
|
+
instructions_to_add = [prev_wait, instruction]
|
|
1358
|
+
prev_wait = None
|
|
1359
|
+
else:
|
|
1360
|
+
instructions_to_add = [instruction]
|
|
1361
|
+
for instr in instructions_to_add:
|
|
1362
|
+
_append_to_schedule(sc_schedule, channel_name, instr)
|
|
1363
|
+
if prev_wait:
|
|
1364
|
+
_append_to_schedule(sc_schedule, channel_name, prev_wait)
|
|
1378
1365
|
pl.segments.append(sc_schedule)
|
|
1379
|
-
|
|
1380
1366
|
return pl
|
|
1381
1367
|
|
|
1382
1368
|
def _set_gate_implementation_shortcut(self, op_name: str) -> None:
|
iqm/pulse/gates/__init__.py
CHANGED
|
@@ -48,7 +48,7 @@ from iqm.pulse.gates.default_gates import _quantum_ops_library
|
|
|
48
48
|
from iqm.pulse.gates.delay import Delay
|
|
49
49
|
from iqm.pulse.gates.flux_multiplexer import FluxMultiplexer_SampleLinear
|
|
50
50
|
from iqm.pulse.gates.measure import Measure_Constant, Measure_Constant_Qnd, Shelved_Measure_Constant
|
|
51
|
-
from iqm.pulse.gates.move import MOVE_CRF_CRF, MOVE_TGSS_CRF
|
|
51
|
+
from iqm.pulse.gates.move import MOVE_CRF_CRF, MOVE_SLEPIAN_CRF, MOVE_TGSS_CRF
|
|
52
52
|
from iqm.pulse.gates.prx import (
|
|
53
53
|
Constant_PRX_with_smooth_rise_fall,
|
|
54
54
|
PRX_DRAGCosineRiseFall,
|
|
@@ -105,6 +105,7 @@ _exposed_implementations: dict[str, type[GateImplementation]] = {
|
|
|
105
105
|
Shelved_Measure_Constant,
|
|
106
106
|
PRX_ModulatedDRAGCosineRiseFall,
|
|
107
107
|
MOVE_CRF_CRF,
|
|
108
|
+
MOVE_SLEPIAN_CRF,
|
|
108
109
|
MOVE_TGSS_CRF,
|
|
109
110
|
RZ_ACStarkShift_CosineRiseFall,
|
|
110
111
|
RZ_ACStarkShift_smoothConstant,
|
iqm/pulse/gates/default_gates.py
CHANGED
|
@@ -35,7 +35,7 @@ from iqm.pulse.gates.cz import (
|
|
|
35
35
|
from iqm.pulse.gates.delay import Delay
|
|
36
36
|
from iqm.pulse.gates.flux_multiplexer import FluxMultiplexer_SampleLinear
|
|
37
37
|
from iqm.pulse.gates.measure import Measure_Constant, Shelved_Measure_Constant
|
|
38
|
-
from iqm.pulse.gates.move import MOVE_CRF_CRF, MOVE_TGSS_CRF
|
|
38
|
+
from iqm.pulse.gates.move import MOVE_CRF_CRF, MOVE_SLEPIAN_CRF, MOVE_TGSS_CRF
|
|
39
39
|
from iqm.pulse.gates.prx import (
|
|
40
40
|
PRX_DRAGCosineRiseFall,
|
|
41
41
|
PRX_DRAGCosineRiseFallSX,
|
|
@@ -89,7 +89,7 @@ _default_implementations = {
|
|
|
89
89
|
"crf_acstarkcrf": CZ_CRF_ACStarkCRF,
|
|
90
90
|
"slepian_acstarkcrf": CZ_Slepian_ACStarkCRF,
|
|
91
91
|
},
|
|
92
|
-
"move": {"tgss_crf": MOVE_TGSS_CRF, "crf_crf": MOVE_CRF_CRF},
|
|
92
|
+
"move": {"tgss_crf": MOVE_TGSS_CRF, "crf_crf": MOVE_CRF_CRF, "slepian_crf": MOVE_SLEPIAN_CRF},
|
|
93
93
|
"cc_prx": {
|
|
94
94
|
"prx_composite": CCPRX_Composite,
|
|
95
95
|
"prx_composite_drag_crf": CCPRX_Composite_DRAGCosineRiseFall,
|
iqm/pulse/gates/move.py
CHANGED
|
@@ -44,7 +44,7 @@ from exa.common.data.parameter import Parameter, Setting
|
|
|
44
44
|
from iqm.pulse.gates.cz import FluxPulseGate
|
|
45
45
|
from iqm.pulse.playlist.instructions import Block, Instruction, VirtualRZ, Wait
|
|
46
46
|
from iqm.pulse.playlist.schedule import Schedule
|
|
47
|
-
from iqm.pulse.playlist.waveforms import CosineRiseFall, TruncatedGaussianSmoothedSquare
|
|
47
|
+
from iqm.pulse.playlist.waveforms import CosineRiseFall, Slepian, TruncatedGaussianSmoothedSquare
|
|
48
48
|
from iqm.pulse.timebox import TimeBox
|
|
49
49
|
from iqm.pulse.utils import normalize_angle
|
|
50
50
|
|
|
@@ -137,6 +137,13 @@ class MOVE_CRF_CRF(MOVE_CustomWaveforms, coupler_wave=CosineRiseFall, qubit_wave
|
|
|
137
137
|
"""Qubit-resonator MOVE gate using the CRF waveform for the coupler and the qubit flux pulse."""
|
|
138
138
|
|
|
139
139
|
|
|
140
|
+
class MOVE_SLEPIAN_CRF(MOVE_CustomWaveforms, coupler_wave=Slepian, qubit_wave=CosineRiseFall):
|
|
141
|
+
# type: ignore[call-arg]
|
|
142
|
+
"""Qubit-resonator MOVE gate using the Slepian waveform for the coupler flux pulse and the
|
|
143
|
+
CRF waveform for the qubit flux pulse.
|
|
144
|
+
"""
|
|
145
|
+
|
|
146
|
+
|
|
140
147
|
class MOVE_TGSS_CRF(MOVE_CustomWaveforms, coupler_wave=TruncatedGaussianSmoothedSquare, qubit_wave=CosineRiseFall):
|
|
141
148
|
# type: ignore[call-arg]
|
|
142
149
|
"""Qubit-resonator MOVE gate using the TGSS waveform for the coupler flux pulse and the
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
iqm/pulse/__init__.py,sha256=FxgHlv3bF8bQCREwOJ1yu_nsrfJq0g0HdovvT1wUnCI,881
|
|
2
2
|
iqm/pulse/base_utils.py,sha256=tLbmnWGmHsjcA8QFCiqvHfgSJJNWS4AVTcD2y4M2ipU,2641
|
|
3
|
-
iqm/pulse/builder.py,sha256=
|
|
3
|
+
iqm/pulse/builder.py,sha256=34y0-5CF4Izo4s7BsVYXOVePuf5SomxZiMdM7Je59PY,66940
|
|
4
4
|
iqm/pulse/circuit_operations.py,sha256=LhOcgSXVYUr6-JzI38uy3r14Bnra9Yu-Zlubg2l_MUA,22665
|
|
5
5
|
iqm/pulse/gate_implementation.py,sha256=1sJ6Vy4DcQBswY5WUOkHKbIkMS3NSCEhovxG9QsdkU4,33898
|
|
6
6
|
iqm/pulse/quantum_ops.py,sha256=VxWOV_XD61JjQl0ugKhgY0TSOhg3CRwcrpLvpzIAcIQ,14732
|
|
@@ -8,16 +8,16 @@ iqm/pulse/scheduler.py,sha256=Y5WL8TwAEzoSnboie8scv9skC5YBmdXKAJ4KTnYn0xU,22690
|
|
|
8
8
|
iqm/pulse/timebox.py,sha256=w3R6VafBXx_cGWrcvI_6x1e6JII_9v1vxQoRSGIjtXE,16591
|
|
9
9
|
iqm/pulse/utils.py,sha256=HyTkMD0er_rZnvDZWM1WscOFxaxGMyRAW_Aw36b0Hdc,7998
|
|
10
10
|
iqm/pulse/validation.py,sha256=-tZWrW201t4nbTQWeZ8M9DixzoN8B0Q63IP57BfDAz0,10733
|
|
11
|
-
iqm/pulse/gates/__init__.py,sha256=
|
|
11
|
+
iqm/pulse/gates/__init__.py,sha256=5QJglgKW1u2C1Ew1-x7ApAEfoNl97HUTvdkE7dC_6kk,13030
|
|
12
12
|
iqm/pulse/gates/barrier.py,sha256=WhYV70lf4lh4Wa9UZuMk2lp9JbUQIu8lzewRC2P7pNE,2546
|
|
13
13
|
iqm/pulse/gates/conditional.py,sha256=3tW5kVt2M2xaTJxaixTErU5DTe91F0uE9BN9kopBEkQ,6242
|
|
14
14
|
iqm/pulse/gates/cz.py,sha256=HAKdR7puauiOIPikW5proQXf_oWauivrPuX1e632h9k,20162
|
|
15
|
-
iqm/pulse/gates/default_gates.py,sha256=
|
|
15
|
+
iqm/pulse/gates/default_gates.py,sha256=w29BbeA3QGSusyGQX5ST9vFvqpSz2zRRrHF1XzSfKc0,9567
|
|
16
16
|
iqm/pulse/gates/delay.py,sha256=nST9dY2JFp_mpKhiSfsYa5yL4hFKcNJSAyCzXjhauQg,3767
|
|
17
17
|
iqm/pulse/gates/enums.py,sha256=ATwb6vZYpfgQ1gQyFPW53JyIKrdAP3FPHm6jV-t9OAk,2532
|
|
18
18
|
iqm/pulse/gates/flux_multiplexer.py,sha256=5psam8_3z796z2nL-A2RKzDGTRDE-7GJ4F0aYCgaPUY,9691
|
|
19
19
|
iqm/pulse/gates/measure.py,sha256=sLr3j7P4C1VAODuUZRWg5tDkPjI0CGFBtQ_mendAHbA,43935
|
|
20
|
-
iqm/pulse/gates/move.py,sha256=
|
|
20
|
+
iqm/pulse/gates/move.py,sha256=zxlVElaMDxKpdPuvqO3EWhdc8HM6c1VYNUTNsNokiAw,17463
|
|
21
21
|
iqm/pulse/gates/prx.py,sha256=yd87JbHU1y40EOzgA1m4m-y8BX6XkHij_uw7o0t-B1s,24596
|
|
22
22
|
iqm/pulse/gates/reset.py,sha256=vYbzaA0pg3r5Oh6Edpu6NPlYoq1M7_tEWnf-7SHig4o,7589
|
|
23
23
|
iqm/pulse/gates/rz.py,sha256=GWOlaHITJojQruu4R8-jIBez0OgFg4olarZkkxIRwRg,9459
|
|
@@ -38,8 +38,8 @@ iqm/pulse/playlist/visualisation/templates/static/logo.png,sha256=rbfQZ6_UEaztpY
|
|
|
38
38
|
iqm/pulse/playlist/visualisation/templates/static/moment.min.js,sha256=4iQZ6BVL4qNKlQ27TExEhBN1HFPvAvAMbFavKKosSWQ,53324
|
|
39
39
|
iqm/pulse/playlist/visualisation/templates/static/vis-timeline-graph2d.min.css,sha256=svzNasPg1yR5gvEaRei2jg-n4Pc3sVyMUWeS6xRAh6U,19837
|
|
40
40
|
iqm/pulse/playlist/visualisation/templates/static/vis-timeline-graph2d.min.js,sha256=OqCqCyA6JnxPz3PGXq_P_9VuSqWptgNt5Ev3T-xjefQ,570288
|
|
41
|
-
iqm_pulse-9.
|
|
42
|
-
iqm_pulse-9.
|
|
43
|
-
iqm_pulse-9.
|
|
44
|
-
iqm_pulse-9.
|
|
45
|
-
iqm_pulse-9.
|
|
41
|
+
iqm_pulse-9.18.0.dist-info/LICENSE.txt,sha256=R6Q7eUrLyoCQgWYorQ8WJmVmWKYU3dxA3jYUp0wwQAw,11332
|
|
42
|
+
iqm_pulse-9.18.0.dist-info/METADATA,sha256=pcJpDrA0hhsKBwlehi500s7fTUSsH7gyJHcr2Ma8Des,14524
|
|
43
|
+
iqm_pulse-9.18.0.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
|
|
44
|
+
iqm_pulse-9.18.0.dist-info/top_level.txt,sha256=NB4XRfyDS6_wG9gMsyX-9LTU7kWnTQxNvkbzIxGv3-c,4
|
|
45
|
+
iqm_pulse-9.18.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|