iqm-pulse 9.4__py3-none-any.whl → 9.6__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.
@@ -66,6 +66,7 @@ from iqm.pulse.gates.reset import Reset_Conditional, Reset_Wait
66
66
  from iqm.pulse.gates.rz import (
67
67
  RZ_ACStarkShift_CosineRiseFall,
68
68
  RZ_ACStarkShift_smoothConstant,
69
+ RZ_PRX_Composite,
69
70
  RZ_Virtual,
70
71
  get_unitary_rz,
71
72
  )
@@ -88,6 +89,7 @@ _exposed_implementations: dict[str, type[GateImplementation]] = {
88
89
  PRX_HdDragSX,
89
90
  SXGate,
90
91
  UGate,
92
+ RZ_PRX_Composite,
91
93
  RZ_Virtual,
92
94
  CZ_CRF_ACStarkCRF,
93
95
  CZ_Slepian_ACStarkCRF,
@@ -47,6 +47,7 @@ from iqm.pulse.gates.prx import (
47
47
  from iqm.pulse.gates.reset import Reset_Conditional, Reset_Wait
48
48
  from iqm.pulse.gates.rz import (
49
49
  RZ_ACStarkShift_CosineRiseFall,
50
+ RZ_PRX_Composite,
50
51
  RZ_Virtual,
51
52
  get_unitary_rz,
52
53
  )
@@ -71,7 +72,7 @@ _default_implementations = {
71
72
  },
72
73
  "u": {"prx_u": UGate},
73
74
  "sx": {"prx_sx": SXGate},
74
- "rz": {"virtual": RZ_Virtual},
75
+ "rz": {"virtual": RZ_Virtual, "prx_composite": RZ_PRX_Composite},
75
76
  "rz_physical": {"ac_stark_crf": RZ_ACStarkShift_CosineRiseFall},
76
77
  "cz": {
77
78
  "tgss": CZ_TruncatedGaussianSmoothedSquare,
@@ -573,3 +573,215 @@ class ProbePulse_CustomWaveforms(CustomIQWaveforms):
573
573
  @classmethod
574
574
  def get_locus_mapping_name(cls, operation_name: str, implementation_name: str) -> str:
575
575
  return PROBE_LINES_LOCUS_MAPPING
576
+
577
+
578
+ class ProbePulse_CustomWaveforms_noIntegration(CustomIQWaveforms):
579
+ """Base class for implementing a probe line probe pulse with custom waveforms in the I and Q channels without
580
+ any integration.
581
+
582
+ Similar to the :class:`ProbePulse_CustomWaveforms` except that signal integration is removed.
583
+ """
584
+
585
+ root_parameters = {
586
+ "frequency": Parameter("", "Readout pulse frequency", "Hz"),
587
+ "duration": Parameter("", "Readout pulse duration", "s"),
588
+ "phase": Parameter("", "Readout pulse phase", "rad"),
589
+ "amplitude_i": Parameter("", "Readout channel I amplitude", ""),
590
+ "amplitude_q": Parameter("", "Readout channel Q amplitude", ""),
591
+ }
592
+
593
+ def __init__(
594
+ self, parent: QuantumOp, name: str, locus: Locus, calibration_data: OILCalibrationData, builder: ScheduleBuilder
595
+ ):
596
+ super().__init__(parent, name, locus, calibration_data, builder)
597
+
598
+ self._multiplexed_timeboxes: dict[tuple[str, str, bool], MultiplexedProbeTimeBox] = {}
599
+ """Cache for :meth:`probe_timebox`."""
600
+
601
+ if len(locus) == 1: # factorizable gates only need calibration on 1-loci
602
+ self._probe_line: ProbeChannelProperties = self.builder.channels[
603
+ self.builder.get_probe_channel(self.locus[0])
604
+ ]
605
+ c_freq = self._probe_line.center_frequency
606
+ if_freq = (calibration_data["frequency"] - c_freq) / self._probe_line.sample_rate
607
+ self._duration = (
608
+ self._probe_line.duration_to_int_samples(
609
+ self._probe_line.round_duration_to_granularity(calibration_data["duration"])
610
+ )
611
+ + self._probe_line.instruction_duration_granularity
612
+ )
613
+
614
+ waveform_params = self.convert_calibration_data(
615
+ calibration_data,
616
+ {k: v for k, v in self.parameters.items() if k not in self.root_parameters or k == "duration"},
617
+ self._probe_line,
618
+ )
619
+ root_params = {k: v for k, v in calibration_data.items() if k in self.root_parameters and k != "duration"}
620
+
621
+ probe_instruction = self._build_instructions(waveform_params, root_params, if_freq)
622
+ self._probe_instruction = probe_instruction
623
+ self._prio_calibration: OILCalibrationData | None = None
624
+ else:
625
+ # we need to store the possible cal_data == priority calibration in order to propagate it to the factored
626
+ # single-component measure calls in :meth:`probe_timebox`
627
+ self._prio_calibration = calibration_data or None
628
+
629
+ def _build_instructions(
630
+ self, waveform_params: OILCalibrationData, root_params: OILCalibrationData, if_freq: float
631
+ ) -> IQPulse:
632
+ """Builds a probe pulse and an acquisition method using the calibration data.
633
+
634
+ Subclasses may override this method if needed.
635
+ """
636
+ if self.dependent_waves:
637
+ wave_i = self.wave_i(**waveform_params)
638
+ wave_q = self.wave_q(**waveform_params)
639
+ else:
640
+ wave_i = self.wave_i(**waveform_params["i"])
641
+ wave_q = self.wave_q(**waveform_params["q"])
642
+
643
+ probe_pulse = IQPulse(
644
+ duration=waveform_params["n_samples"],
645
+ wave_i=wave_i,
646
+ wave_q=wave_q,
647
+ scale_i=root_params["amplitude_i"],
648
+ scale_q=root_params["amplitude_q"],
649
+ phase=root_params["phase"],
650
+ modulation_frequency=if_freq,
651
+ )
652
+
653
+ return probe_pulse
654
+
655
+ def probe_timebox(
656
+ self, key: str = "", feedback_key: str = "", do_acquisition: bool = False
657
+ ) -> MultiplexedProbeTimeBox:
658
+ """Returns a "naked" probe timebox that supports convenient multiplexing through
659
+ ``MultiplexedProbeTimeBox.__add__``.
660
+
661
+ This method can be used if the user wants to control the multiplexing explicitly. With two
662
+ ``MultiplexedProbeTimeBox``es ``A`` and ``B`` the result ``A + B`` has all the ``ReadoutTrigger`` instructions
663
+ on each probe channel of ``A`` and ``B`` multiplexed together and played simultaneously.
664
+
665
+ Args:
666
+ key: The readout results generated on this trigger will be assigned to
667
+ ``f"{qubit}__{key}"``, where ``qubit`` goes over the component names in ``self.locus``. If empty,
668
+ the key `"readout.result"` will be used to maintain backwards compatibility.
669
+ feedback_key: The signals generated by this measure operation are routed using this key for
670
+ fast feedback purposes. See :meth:`__call__`.
671
+ do_acquisition: if False, no acquisitions are added.
672
+
673
+ Returns:
674
+ MultiplexedProbeTimeBox containing the ReadoutTrigger instruction.
675
+
676
+ """
677
+ args = (key, feedback_key, do_acquisition)
678
+ # additional caching for probe timeboxes due to the fact that both ._call and .time_trace use this
679
+ if args not in self._multiplexed_timeboxes:
680
+ if len(self.locus) == 1:
681
+ multiplexed_iq = MultiplexedIQPulse(
682
+ duration=self._probe_instruction.duration,
683
+ entries=((self._probe_instruction, 0),),
684
+ )
685
+ readout_trigger = ReadoutTrigger(
686
+ probe_pulse=multiplexed_iq,
687
+ acquisitions=(),
688
+ duration=self._duration,
689
+ )
690
+ probe_channel = self.builder.get_probe_channel(self.locus[0])
691
+ try:
692
+ drive_channel = self.builder.get_drive_channel(self.locus[0])
693
+ except KeyError:
694
+ drive_channel = ""
695
+
696
+ if drive_channel:
697
+ # drive channel must be blocked, to prevent DD insertion while measurement is taking place
698
+ # unfortunately we must allow for different channel sample rates because of UHFQA
699
+ channels = self.builder.channels
700
+ drive_channel_props = channels[drive_channel]
701
+ rt_duration_in_seconds = channels[probe_channel].duration_to_seconds(readout_trigger.duration)
702
+ block_duration = drive_channel_props.duration_to_int_samples(
703
+ drive_channel_props.round_duration_to_granularity(
704
+ rt_duration_in_seconds, round_up=True, force_min_duration=True
705
+ )
706
+ )
707
+ probe_timebox = MultiplexedProbeTimeBox.from_readout_trigger(
708
+ readout_trigger=readout_trigger,
709
+ probe_channel=probe_channel,
710
+ locus_components=self.locus,
711
+ label=f"{self.__class__.__name__} on {self.locus}",
712
+ block_channels=[drive_channel],
713
+ block_duration=block_duration,
714
+ )
715
+ else:
716
+ probe_timebox = MultiplexedProbeTimeBox.from_readout_trigger(
717
+ readout_trigger=readout_trigger,
718
+ probe_channel=probe_channel,
719
+ locus_components=self.locus,
720
+ label=f"{self.__class__.__name__} on {self.locus}",
721
+ )
722
+ else:
723
+ probe_timeboxes = [
724
+ self.builder.get_implementation(
725
+ self.parent.name, (c,), impl_name=self.name, priority_calibration=self._prio_calibration
726
+ ).probe_timebox(key, feedback_key, do_acquisition)
727
+ for c in self.locus
728
+ ]
729
+ probe_timebox = functools.reduce(lambda x, y: x + y, probe_timeboxes)
730
+ probe_timebox.neighborhood_components[0] = set(
731
+ self.locus + (self.builder.chip_topology.component_to_probe_line[self.locus[0]],)
732
+ )
733
+
734
+ self._multiplexed_timeboxes[args] = probe_timebox
735
+ return self._multiplexed_timeboxes[args]
736
+
737
+ def _call(self, key: str = "", feedback_key: str = "") -> TimeBox:
738
+ """Returns a TimeBox containing the multiplexed simultaneous measurement.
739
+
740
+ If ``len(self.locus) == 1``, the TimeBox contains the measurement for just that component, otherwise
741
+ the measurements of components that belong to the same probeline are multiplexed together.
742
+
743
+ The returned :class:`.TimeBox` instances behave like any other TimeBox in scheduling and circuit
744
+ generation. With measurement TimeBoxes ``A`` and ``B`` the result ``A + B`` first plays the ``ReadoutTrigger``
745
+ instructions of ``A`` and only then those of ``B`` in each probe channel. If the multiplexing features of
746
+ :class:`.MultiplexedProbeTimeBox` are needed, the method :meth:`probe_timebox` can be used.
747
+
748
+ In scheduling, the returned TimeBox blocks the locus components and the probe
749
+ lines they are associated with.
750
+
751
+ Args:
752
+ key: Readout results generated on this trigger will be assigned to the acquisition labels
753
+ ``f"{qubit}__{key}"``, where ``qubit`` goes over the component names in ``self.locus``.
754
+ If empty, the key ``"readout.result"`` will be used to maintain backwards compatibility.
755
+ feedback_key: If the readout mode is "threshold", the results generated by this ``measure`` operation
756
+ are routed using the label ``f"{qubit}__{feedback_key}"`` for fast feedback purposes.
757
+ The signals are picked up by :class:`.ConditionalInstruction`s that have the same label.
758
+ The default value ``""`` means the signal is not routed anywhere. TODO: currently the HW does not
759
+ support multiple feedback keys per drive channel, so the actual key used will be ``FEEDBACK_KEY``
760
+ whenever any non-empty key is inputted. When the HW is improved, the actual key the user inputs
761
+ should be passed.
762
+
763
+ Returns:
764
+ TimeBox containing the :class:`.ReadoutTrigger` instruction.
765
+
766
+ """
767
+ final_box = TimeBox.composite(
768
+ [self.probe_timebox(key=key, feedback_key=feedback_key)], label=f"Readout on {self.locus}"
769
+ )
770
+ final_box.neighborhood_components[0] = final_box.children[0].neighborhood_components[0]
771
+ return final_box
772
+
773
+ def duration_in_seconds(self) -> float:
774
+ probe_timebox = self.probe_timebox()
775
+ readout_schedule = probe_timebox.atom
776
+ return readout_schedule.duration_in_seconds(self.builder.channels)
777
+
778
+ @classmethod
779
+ def get_locus_mapping_name(cls, operation_name: str, implementation_name: str) -> str:
780
+ return SINGLE_COMPONENTS_WITH_READOUT_LOCUS_MAPPING
781
+
782
+
783
+ class Probe_Constant(ProbePulse_CustomWaveforms_noIntegration, wave_i=Constant, wave_q=Constant): # type: ignore[call-arg]
784
+ """Implementation of a single-qubit projective, dispersive measurement in the Z basis.
785
+
786
+ Uses a constant probe pulse.
787
+ """
iqm/pulse/gates/rz.py CHANGED
@@ -32,6 +32,7 @@ import numpy as np
32
32
  from exa.common.data.parameter import Parameter
33
33
  from iqm.pulse.gate_implementation import (
34
34
  SINGLE_COMPONENTS_WITH_DRIVE_LOCUS_MAPPING,
35
+ CompositeGate,
35
36
  GateImplementation,
36
37
  Locus,
37
38
  OILCalibrationData,
@@ -46,7 +47,7 @@ from iqm.pulse.utils import normalize_angle, phase_transformation
46
47
  if TYPE_CHECKING: # pragma: no cover
47
48
  from iqm.pulse.builder import ScheduleBuilder
48
49
  from iqm.pulse.quantum_ops import QuantumOp
49
- from iqm.pulse.timebox import TimeBox
50
+ from iqm.pulse.timebox import TimeBox
50
51
 
51
52
 
52
53
  @lru_cache
@@ -245,3 +246,22 @@ class RZ_ACStarkShift_smoothConstant(
245
246
 
246
247
  def __call__(self):
247
248
  return super().__call__(angle=np.pi)
249
+
250
+
251
+ class RZ_PRX_Composite(CompositeGate):
252
+ """RZ gate implemented as a sequence of PRX gates."""
253
+
254
+ registered_gates = ["prx"]
255
+
256
+ def __init__(self, parent, name, locus, calibration_data, builder):
257
+ super().__init__(parent, name, locus, calibration_data, builder)
258
+
259
+ def __call__(self, angle: float) -> TimeBox:
260
+ prx = self.build("prx", self.locus)
261
+ return TimeBox.composite(
262
+ [
263
+ prx.ry(np.pi / 2),
264
+ prx.rx(angle),
265
+ prx.ry(-np.pi / 2),
266
+ ]
267
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: iqm-pulse
3
- Version: 9.4
3
+ Version: 9.6
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
@@ -8,19 +8,19 @@ iqm/pulse/scheduler.py,sha256=jBi68_Y1RVNe3aDmP4wmudDs5vXCHZm-UXl3IpgNDDM,22738
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=2v1wRMyQlyzScBk2D3wit3C2qbPhUHpSJbGPfSUespY,12878
11
+ iqm/pulse/gates/__init__.py,sha256=zMz1jDQg6EFsTreNu0NyhOWpecWnbAntrvSlJQa7Xoo,12926
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=QgV-mn2aPDbfNplwEi18Lll4Zle-IELpn43IPM6Q_w8,20141
15
- iqm/pulse/gates/default_gates.py,sha256=nBVzyhU1Xj-jCuC-0e9OZPjOJShg7yFeS7oqeqPCrdw,9356
15
+ iqm/pulse/gates/default_gates.py,sha256=kLNYjt-ZXYPvfBS1p8pi7e3gZz2UnMSWS4S2Xmj6omg,9413
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=lnlynR_SWM6Wp7RjVcyParCSNKacKargEC5lLF5jwKU,9692
19
- iqm/pulse/gates/measure.py,sha256=VlcPufdl3tG2MNcRkUzKjBz5BFqVVqBOCn6-mPTRhoc,29518
19
+ iqm/pulse/gates/measure.py,sha256=izqaO4Pxxb7THJhs6tx3QT_YCFDpdt8Mi30E-gwvM7g,40429
20
20
  iqm/pulse/gates/move.py,sha256=yKY-Et4YJV0KmcDwN0yE3oHgDtLL-Xfgy1G_InsJN0U,17182
21
21
  iqm/pulse/gates/prx.py,sha256=SaJHcVu-NURUBTF5LtmTwwK1qcCtXA89NA5VwJXBM1o,24504
22
22
  iqm/pulse/gates/reset.py,sha256=ZgliZd2yVJZuVyeVt6qnnVTt3CGb-cLCIWmoq4nS4lk,7574
23
- iqm/pulse/gates/rz.py,sha256=hd0tEbCUzA7sRRQ1PWwqJTmLL9ikvL2xYot6aBoq-yc,8856
23
+ iqm/pulse/gates/rz.py,sha256=6iQudKjEhze0DkGDY1GZIJ7IW1QqxL7Fy74lTrJ4o8s,9416
24
24
  iqm/pulse/gates/sx.py,sha256=V8e94LHRLkXLjSSeuKxZQbhwgGDAWdQxsfhbYi4gtp8,1673
25
25
  iqm/pulse/gates/u.py,sha256=2kmbTYprrkVP4EbwGXNZcT5lzInjjOAvq8vk0lw57YY,5256
26
26
  iqm/pulse/playlist/__init__.py,sha256=XW-7Po_vCzhkk1Js06K8P-5srPpBuPHkqpc1yhL_Zx4,997
@@ -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.4.dist-info/LICENSE.txt,sha256=R6Q7eUrLyoCQgWYorQ8WJmVmWKYU3dxA3jYUp0wwQAw,11332
42
- iqm_pulse-9.4.dist-info/METADATA,sha256=4e_r2lx7UPgyFrWWAlASRdH0t5F2KMMP1hF-ziuMWj0,14520
43
- iqm_pulse-9.4.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
44
- iqm_pulse-9.4.dist-info/top_level.txt,sha256=NB4XRfyDS6_wG9gMsyX-9LTU7kWnTQxNvkbzIxGv3-c,4
45
- iqm_pulse-9.4.dist-info/RECORD,,
41
+ iqm_pulse-9.6.dist-info/LICENSE.txt,sha256=R6Q7eUrLyoCQgWYorQ8WJmVmWKYU3dxA3jYUp0wwQAw,11332
42
+ iqm_pulse-9.6.dist-info/METADATA,sha256=PvoI-osxl1RWW5_IrkkNTiyl-1SEQYjCPFzWFHPNAaQ,14520
43
+ iqm_pulse-9.6.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
44
+ iqm_pulse-9.6.dist-info/top_level.txt,sha256=NB4XRfyDS6_wG9gMsyX-9LTU7kWnTQxNvkbzIxGv3-c,4
45
+ iqm_pulse-9.6.dist-info/RECORD,,